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 false
initalizing
is never set to false
initialize
function, in, say Staking.sol
and set the governance address to what they want