This agent detects when an attacker could trigger a selfdestruct of a UUPS implementation contract, leaving a proxy contract permanently broken. The agent is separated into three threads:
- First thread detects contracts that are not initialized.
- Second thread detects the main exploit and tries to anticipate it - if new contract logic exists but selfdestruct method is reachable in the byte-code - this thread will provide the alert too.
- Third thread detects when a contract is initialized by TransferOwnership event where the previous owner was 0x0000000000000000000000000000000000000000
For a detailed description of the issue refer to the post-mortem.
- Ethereum
-
UUPS-EXPLOIT
- Fired when there is
Upgraded(address)event in the log and new implementation address returns an empty byte-code - Severity is always set to
Critical - Type is always set to
Exploit - Metadata:
tx_hash- hash of the transactionnew_implementation- address of the new implementationattacker_address- sender of the transaction
- Fired when there is
-
LOGIC-NOT-INIT
- Fired when the delegatecall target address has an owner with an address 0x0000000000000000000000000000000000000000
- Severity is always set to
High - Type is always set to
Unknown - Metadata:
tx_hash- hash of the transactioncontract- address of the implementationproxy- address of the proxy
-
LOGIC-CAN-SELFDESTRUCT
- Fired when selfdestruct method is reachable in the byte-code
- Severity is always set to
High - Type is always set to
Unknown - Metadata:
tx_hash- hash of the transactionnew_implementation- address of the new implementation
-
CONTRACT-INIT
- Fired when a contract is initialized by the TransferOwnership event where the previous owner was 0x0000000000000000000000000000000000000000
- Severity is always set to
Medium - Type is always set to
Info - Metadata:
tx_hash- hash of the transactionnew_owner- address of the new ownercontract- address of the implementation
- Python:
3.10
npm startThis attack has not, as far as we know, been executed on chain.
You can test the agent using
npm testThere are 6 test that should pass:
test_returns_main_exploit_finding()test_returns_finding_if_logic_contract_not_initialized()test_returns_finding_if_new_logic_contract_can_be_selfdestructed()test_returns_finding_if_contract_was_initialized()test_returns_zero_finding_if_upgraded_event_is_correct_and_code_cant_selfdestruct()test_returns_zero_finding_if_logic_contract_is_initialized_already()
For these purposes, web3 and event mocks are used. You can check web3 mock in src/test/web3_mock.py
and events mocks in src/test/agent_test.py
