software-mansion / starknet.py

✨ 🐍 Python SDK for Starknet.
https://starknetpy.rtfd.io/
MIT License
259 stars 74 forks source link

[BUG] Proxy contracts are not able to find ABIs #128

Closed antazoey closed 2 years ago

antazoey commented 2 years ago

When I interact with a smart-contract via calling a mutable method on the live Testnet (goerli alpha), I get an Unknown location error.

Python version

Python 3.7.9

Expected Behavior

I can call mutable methods on contracts from goerli

Current Behavior

I get the following error:

ERROR: (ContractLogicError) Error at pc=0:32:Got an exception while executing a hint.Cairo traceback (most recent call last):Unknown location (pc=0:497)Unknown location (pc=0:456)Unknown location (pc=0:513)Error in the called contract (0x7394cbe418daa16e42b87ba67372d4ab4a5df0b05c6e554d158458ce245bc10):Error at pc=0:6:Got an exception while executing a hint.Cairo traceback (most recent call last):Unknown location (pc=0:795)Unknown location (pc=0:772)Unknown location (pc=0:1232)Traceback (most recent call last):  File "<hint0>", line 3, in <module>AssertionError: assert_not_zero failed: 0 = 0.').

I am using the test token contract deployed to 0x07394cbe418daa16e42b87ba67372d4ab4a5df0b05c6e554d158458ce245bc10

When I deploy an ERC20 to my local starknet-devnet, I can call mutable methods and things work just fine.

Possible Solution

We need to grab the ABI from the implementation contract.

Steps to Reproduce

from starknet_py.contract import Contract
from starknet_py.net import AccountClient
from starknet_py.net import KeyPair

# This account comes from ArgentX and is a proxy contract.
# The error I get is that it cannot find the __execute__ ABI.
# The __execute__ method needs to be grabbed from the implementation contract.
account_address = 2976162931320574283751166485501184860501729793478009661243729394508001134570

# Create the account client (note: my pkey is omitted for obvious reasons)
key_pair = KeyPair(
    private_key=******,
    public_key=888158711641686699726990655481927574337047407568
)
account_client = AccountClient(
    account_address,
    key_pair,
    'https://alpha4.starknet.io',
    chain=1536727068981429685321,
)

my_other_account = 3037460148268451690947737348211282823053350676597561718645135357343745417603

# Init the ETH token contract from its address
token_address = "0x07394cbe418daa16e42b87ba67372d4ab4a5df0b05c6e554d158458ce245bc10"
token_contract = Contract.from_address_sync(token_address, account_client)

receipt = token_contract.functions["transfer"].invoke_sync(my_other_account, 100, max_fee=100)
print(receipt)  # Does not get here

Context (Environment)

Trying to interact with the ETH contract (which is a proxy) Also, trying to use my Argent X account (which is a proxy) In general, I have trouble with proxy contracts

Detailed Description

Fetch ABI from proxy first by calling implementation()

Possible Implementation

antazoey commented 2 years ago

Similar to this, when an method uses a struct types as input and that contract is a proxy, it does not know about the struct ABI and fails