Audius Governance Takeover Post-Mortem 7/23/22 | Audius Blog
Details provided:
Contract Structure
S Admin(Proxy) | Implementation
-----------------|-----------------
0 proxyAdmin | initialized, initializing (OZ) <------ Storage Collision
-----------------|-----------------
1 | isInitialized (V2)
-----------------|-----------------
...
-----------------|-----------------
[0x3...bc] |
implementation |
-----------------|-----------------
OZ Initializable has 2 boolean values packed into storage slot 0 (2/32 bytes):
Audius has a governance contract that stores the address proxyAdmin at storage slot 0. It also acts as a Proxy, so will cause collisions with the implementation contract in _delegate
Recall how a call to an OZ upgradeable contract works:
0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc)The problem, therefore, was storing information about the Admin in the Proxy contract.
initializing always passes, because initially initializing is set to trueisTopLevelCall always returns false because initialized is true and so !initalized is falseinitalizing is never set to falseinitialize function, in, say Staking.sol and set the governance address to what they want