Alex Otsu

Posted on Feb 08, 2022Read on Mirror.xyz

Interacting with Deployed Proxy Smart Contracts with Remix

Making Arbitrary Calls from the Browser

I recently found myself with the need to call a single read function from a contract deployed on the Polygon network, but was unable to do so through polygonscan (the L2 version of etherscan) because it was a proxy.

Pictured: my personal Friday the 13th

Fortunately, Remix and MetaMask make it easy to call the function from within the browser in a few easy steps:

  1. Locating the contract address
  2. Identifying the function to be called
  3. Connecting to the desired network and calling the function

In this piece, we will first walk through the above actions at a high level before applying them to a concrete example case.

Steps

First, the contract address must be identified. Almost all dApps will provide a link to the contract that they use, and following it should take you to a block explorer page that looks similar to the below screenshot:

Note down the highlighted address somewhere

Once the address is known, we need to find the function definition for the function we want to call. That includes the function name, input types, state mutability, and return values. In the example case (more on that in the next section), that happened to be `tokenURI(uint256 tokenId) public view returns(string memory)`. We need these to recreate a limited version of an ABI that we will use to call the function at the contract address.

Next, connect to your desired network in MetaMask. If you are attempting to interact with a contract on the Ethereum mainnet or any of its four widely used testnets, those can be selected through the dropdown. If you are connecting to Polygon, you need to select the “Custom RPC” option and enter the following settings (more detailed instructions available in this article):

Image credit: Stakingbits

Now it is time to fire up Remix, an in-browser Solidity IDE. While connected to your target network in MetaMask, select “Injected Web3” from the “ENVIRONMENT” dropdown and connect your MetaMask to the page when prompted.

In the code window, create a contract with whatever name you want. Copy over the function definition from earlier, but leave the function itself empty.

Making sure that the correct contract is selected in the “CONTRACT” field of the sidebar, paste the original contract address under “OR” and click “At Address”. The “contract” that appears beneath provides very specific access (one function in this case) to the original, full-featured contract deployed to that address.

You can now interact with the specified function on that contract and access the deployed version’s live values.

Case Study

The original problem I was trying to solve was identifying the storage location of Autograph sports memorabilia NFT metadata. Verifying that metadata is stored on a decentralized file system like IPFS is important for the immutability of the NFT itself, so I started with searching Autograph’s site for its contract addresses.

After some poking around, I was redirected to DraftKings where the address was clearly published. Address secured.

Recall that the next step is identifying the function definition. The link directed to the token page on polygonscan, and navigating to the contract page led to the view shown in the first image of the “Steps” section. The functions on a standard verified contract can usually be accessed from there, but that was not the case with this proxy contract. However, because it is a proxy, there had to be a reference its logic contract address somewhere.

Line 636 specifies that the implementation address can be read directly from contract storage using the `eth_getStorageAt` RPC call, but there was an even simpler solution. The contract’s “Code” page tells us that identical ByteCode had been deployed at another contract location (0x584…970).

That led to yet another contract page, but this time there was an option to “Read as Proxy”! Thank you, polygonscan team! Scrolling down to the bottom of the page, the desired function definition is clearly visible: `TokenURI(tokenId uint256)`, with a string return value.

The function could not be called directly from that polygonscan page because it was not attached to the correct contract, but I had the requisite information for calling the function through Remix: contract address, function definition, and network.

Following the remainder of the steps from the first section identified the URI of the token at index `1` as “https://gateway.autograph.io/ipfs/QmRDyvnLH5cG29v1rrsow4t47g3HT96zMYyvBgAe1k6rog”.

“IPFS” was in the URI, which was a good start. However, the link still pointed back to a hosted endpoint, which is not optimal. I used an independent IPFS gateway (IPFS.io) to verify that the content at content id (“QmR…rog”) matched in both places. And it did!

While it is technically better practice to point a smart contract URI directly to an IPFS address, the contract analysis shows that buyers of Autograph NFTs can have relative certainty that the content of their purchases is immutable. And by using the techniques described in this piece, you have the tools to do due diligence for *your *next NFT purchase on your own.