Etherscan is the go-to for transparency on Ethereum, showing users the implementation behind any proxy contract they’re interacting with (as long as it complies with the ERC1967 standard) . But what if we told you there’s a way to bend Etherscan's mechanism where it shows one implementation… while our contract runs a totally different one?
Let’s break down how this works and how we set up a hybrid proxy that “fooled” Etherscan’s detection system. By combining both the ERC1967 and Beacon Proxy standards, we were able to show Etherscan display one thing while the proxy actually points elsewhere.
Before we dive into the details, we should mention the simplest way to mislead Etherscan is to fill the ERC1967 storage slot with any contract address, verify it as a proxy, and then customize the code however we like. Etherscan will display the implementation as the one in the ERC1967 slot, even though we’ve directed it elsewhere. However, our goal was to use well-known contracts and add or blend subtle logic to make everything appear legitimate to the untrained eye.
The Blueprint: ERC1967 + Beacon Proxy
Here’s what we did: we built a hybrid proxy that inherits from both the ERC1967Proxy and BeaconProxy standards. Each of these standards has its own way of handling the implementation logic.
- ERC1967 Proxy uses a fixed storage slot for its implementation address, and this is what Etherscan usually detects and displays.
- Beacon Proxy doesn’t have a direct implementation address. Instead, it points to a separate Beacon contract that itself holds the implementation address. When you update the Beacon, all proxies pointing to it automatically use the new implementation.
So, in this hybrid setup, we gave our proxy both an ERC1967 implementation slot and a Beacon address. This created a sneaky setup where:
- Etherscan would read the ERC1967 slot and happily display whatever implementation address was stored there.
- Meanwhile, our proxy was actually following the Beacon. Change the Beacon, and our proxy points to the new implementation, but Etherscan? It still shows the old one stored in the ERC1967 slot!
Let’s check out the code setup that made it happen:
How It Worked in Action
With this **TrickOrTreat** contract, we could point Etherscan to a nice, innocent implementation through the ERC1967 slot. But then, by updating the Beacon to a completely different contract, our proxy was running a new implementation while Etherscan was none the wiser!
We first deployed our TrickOrTreat pointing to Implementation A at address 0x82501f6af6e95a7ff23c98dc5b424f2027304d00 in the ERC1967 slot and the beacon implementation. Everyone on Etherscan sees Implementation A and feels comfortable that’s what they’re interacting with.
Etherscan ABI for the TrickOrTreat:
As seen, Etherscan doesn’t even shows the implementation as upgradeable.
Now comes the magic: we update our Beacon’s implementation address to point to Implementation B. The proxy now uses Implementation B at address 0x0843eee18a02765b03c196ca55689eddd9cdfa83, but Etherscan’s still hanging out with Implementation A from the ERC1967 slot. So what you see on Etherscan is no longer what you get!
As seen we used a function not known to Etherscan, not shown on the code tab and still the transaction was approved.
Actually the implementation was changed even sooner, as seen below, transaction with hash 0xb99537340167cebe89c9d6c99c8bbf6d113d9443bcb7a0ddf3fd68e82ced5d5a is interacting with the unverified implementation.
Food for thought - our treat, on the house
All the code above (except the unverified parts) appears completely innocent. We simply combined two OpenZeppelin proxy patterns (innocently, of course 😉), yet the result is a powerful—and potentially dangerous—misleading effect.
P.S 1: Fooling Etherscan was once talked about in a previous post of ours about the chainswap hack (Go directly to the blog post about chainswap).
P.S 2: Combining two OZ contracts and “accidentally” create an unwanted behavior happened in the thirdweb incident
Conclusion
About the author
Eyal has many years of experience in software development, cyber security and more. Before joining spherex technologies as Head of Engineering. Eyal served 10 years in the Israeli intelligence doing software development, cyber research and leading teams, projects and groups.