Read calls in Remix using a Proxy

On Remix, I’ve got a Proxy contract working with a NFT Implementation.
I am able to perform transaction calls (mint, transfer, etc) via the Proxy by passing args at the CALLDATA text field on Remix.
However, I am not able to perform read calls (balanceOf, totalSupply) when I pass in args at the CALLDATA text field.

alos Could you please help me understand how it would make a difference whether the caller is admin or not?

1 Like

Hi @Tezas,

Welcome to the community forum :wave:. Thanks for posting here.

I assume that you deployed a logic contract and proxy manually on Remix rather than using the OpenZeppelin CLI? I also assume that you didn’t deploy a ProxyAdmin contract to be the admin of the proxy.

Would you mind sharing some details on how you deployed the contracts?

As for how to interact with your contract:

If the caller is the admin of the proxy (the address with rights to upgrade the proxy), then the proxy will not delegate any calls, and only answer any messages it understands.

If the caller is any other address, the proxy will always delegate a call, no matter if it matches one of the proxy’s functions.

See the documentation for details:
https://docs.openzeppelin.com/upgrades/2.8/proxies#transparent-proxies-and-function-clashes

This means if you want to interact with your contract, you need to call the functions using the address of the proxy from an account that isn’t the admin of the proxy. So you would need to change accounts in Remix/MetaMask.

1 Like

Thank you for the suggestions. I tried both cases : with and without the Proxy admin, and was able to successfully execute delegatecall on the implementation contract during both occasions.

I do not have function collisions between the Proxy and the Implementation contracts. What I’m trying to understand is how I can access the storage values from within the Proxy contract.

Here are my steps on Remix.

  1. With accounts[0], deployed the NFTInitializable contract (Implementation)

  2. With accounts[0], deployed the AdminUpgradeabilityProxy contract with the following input parameters
    i. NFTInitializable contract address
    ii. accounts[0]
    iii. initialize data for NFT contract

  3. With accounts[1] Minted a NFT token by calling AdminUpgradeabilityProxy.mint(). I could see Transfer events being fired, so I assume tokens were transferred to accounts[1].

  4. With accounts[1], passed encodedHex of “balanceOf(accounts[1])” to AdminUpgradeabilityProxy. Got 0.

  5. With accounts[0], passed encodedHex of “balanceOf(accounts[1])” to AdminUpgradeabilityProxy. Got the expected error Cannot call fallback function from the proxy admin.

I’m trying to understand how I can get the correct token balance from the AdminUpgradeabilityProxy contract by accessing it’s storage, aka, Step 4, which should not be 0, since accounts[1] has been transferred tokens.

Note:

  1. The solidity version I’m using is 0.6.12, so I’ve modified OZ’s upgradeability contracts to accommodate Solidity’s v0.6.0 breaking changes.
  2. I do not have any extra method or variable in the AdminUpgradeabilityProxy contract code, apart from the code already present in OZ’s upgradeability/AdminUpgradeabilityProxy.sol.
1 Like

Hi @Tezas,

I don’t think your encoding of balanceOf is correct.

You can to use Remix to interact with a contract at a specific address. (see At Address is the Remix documentation: https://remix-ide.readthedocs.io/en/latest/run.html#initiate-instance)
So you should be able to specify the implementation contract with the address of the proxy.

You can then call using a non-admin account (such as accounts[1]) to interact with the contract.

Works well when being deployed on the oz sdk.

1 Like