Masquerading code in Etherscan
Yoav Weiss - Ethereum Foundation - @yoavw
Oren Fine - SphereX - @fineoren
Luke: How do I know if I can trust this contract, Master Yoda?
Yoda: Trust, you seek, young Skywalker. The contract, a web of code it is. The source, use you must.
Luke: But how do I discern which source to rely upon, Master Yoda?
Yoda: Judge not by appearances, but by the Force's guidance. Feel the currents, sense the truth. Within you, the answer lies.
Bait & Switch techniques
Show legitimate code, execute bad code.
Examples
(I) Hiding in plain sight
7576 lines of code, 99.99% legit (literally!)
Three transferOwnership funcs - guess which one is used
onlyOwner maybe?
(II) Fake proxy
(III) The non-proxy proxy
(IV) Selector collisions
Vault implementation
keccak(“vaultManagers(address)”)[0:4] == 0xbab82c22
Vault proxy
keccak("IMGURL()")[0:4] == keccak(“vaultManagers(address)”)[0:4] == 0xbab82c22
Number in a Vault - only managers can set the number
IMGURL shadows vaultManagers
Anyone is a manager!
Non-manager address set the number!
(V) Legit code - malicious initialization
Unmodified Safe
Only one visible signer
Etherscan confirms: One legit signer
…but also invisible ones if you know where to look
…and they can transact!
authQuotaOf
Caption
Let’s make it right this time
Obfuscating Delegate Calls
The Untold Story of the 2nd Chainswap Hack
Let’s starts with Etherscan
Implementation contract’s code is verified
Caption
Caption
Caption
Caption
Caption
And now dig into attacker’s transaction
Attacker calls receive() function, ends up in unverified contract
Caption
Caption
Caption
What just happened?
We’ll make a long story - short
Caption
Digging into the “delegate” hole
What used to be a mapping became a function
Caption
authQuotaOf
Caption
At last, the root cause:
The difference between theory and practice
Caption
Conclusion