On Etherscan, interacting with upgradeable contracts using a proxy standard was a real pain point. Some of you may find the below issues sounding familiar:
- The Read/Write Contract functionality refers to the current contract address, which is either the implementation or the storage contract and therefore there is no straightforward way to interact across (or at the very least, read) a proxy contract on Etherscan.
- Some proxy contract implementations have the implementation contract variable set to internal/private (for good reason, e.g. Transparent Proxy Pattern), which makes it harder for users to figure out where the implementation address is.
To help with this, we have recently worked to support several proxy contract standards, notably:
- OpenZeppelin’s Unstructured Storage Proxies
- OpenZeppelin’s Eternal Storage
- EIP-1967 Transparent Proxy Pattern
- EIP-1822 Universal Upgradeable Proxy Standard
And for contracts which uses their custom implementations, we also use a currently experimental process which guesstimates the implementation address from the transactions done historically.
Note that this feature is still new and experimental, there could be bugs and definitely more room for improvement — Always happy to receive feedback.
To access this feature, a contract must first be flagged as a proxy contract — The heuristic involved being that we check if there is a delegeteCall opcode sequence, and if yes, the below button will be displayed:
Clicking on the button will load the Proxy Contract verification page. Clicking “Verify” will run the checks to obtain the implementation contract.
If successfully done, we will get a happy green message — Things can still be inaccurate so do let us know if it is the case.
Once saved, returning to the Contract tab of the proxy/storage contract page will display a new “Read as Proxy” and “Write as Proxy” sections, where the ABI used to load these read/write fields are the implementation contract’s ABI.
If we are not able to obtain an implementation address display flagging the contract as a proxy contract, the below message will be shown. Likewise, please contact us if this is a mistake.
What if the implementation address was upgraded?
If the proxy contract’s implementation address had been upgraded, just re-run the verification process and the new implementation address will be noted and stored in our database.
Naturally, as far as programming heuristics go there are a few caveats:
- Contracts showing “is this a proxy?” may not actually be a proxy contract —An example are contracts relying on libraries which also use the delegateCall opcode to forward storage data for manipulation.
- Always practice caution when interacting with smart contracts on the Ethereum network. The proxy contract may or may not be delegating the call to an external contract as detected, or the delegateCall function may not even be reachable. Trust, but verify.
- For custom proxy contracts, we use Parity’s vmtrace to attempt detection of a delegateCall subcall, and retrieve the “to” address involved. Which means a transaction involving the implementation address has to be done prior, therefore would not work on newly deployed contracts/if there is a recent implementation address change. This is highly experimental, and may/may not be retained as a feature.
Hope this feature helps! Feedback is always welcomed, and we are back to #BUIDLing!