Type: #blockchain
Project: Optimism
Date: 02/02/22
Blockchain: OPTIMISM + METIS
Problem: Selfdestuct doesn't subtract value from the contract.
Optimism is a L2 blockchain. It has it's own EVM which is called OVM - a fork with slight changes.
Optimism modified Geth to apply patches to StateDB to store the native balances in an ERC-20 token storage state. ETH is still represented internally as an ERC-20 token OVM_ETH. It's crucial to understand, that under the hood native balance of tokens is represented in ERC-20, it's also important to understand that since Optimism is a fork it's still has stateObject which represents ETH value and equals to the OVM_ETH.
Solidity compiler has interesting feature: selfdestruct(address) method, which is used for destroying all bytecode from the calling contract address and transfering all Ether held to the target address allows interacting with the destructed contract after the opcode invocation, if called in the same transaction.
The issue in Optimism was that with setting the balance of an account after selfdestruct to 0:
stateObject.data.Balance = new(big.Int)
Optimism client sets the balance to zero directly on the stateObject instead of ERC-20 OVM_ETH contract.
The Hacker could:
1) Creates an exploit contract that contains two internal functions. One with selfdestruct, and a second that withdraws the balance of the contract to the caller. The function with selfdestruct sends the contract’s balance to itself. In this case the contract will double its ERC-20 balance of native token.
2) The attacker deploys the contracts and in the constructor executes calls to the selfdestruct function multiple times in a for loop.
3) After the for loop is finished, the constructor calls the second internal function of the exploit contract to transfer the inflated funds to the attacker.
4) The exploit contract is destroyed at the end of the transaction, hacker takes all the profit.
Discoverer: Saurik
Harm: > 1 B $, 2 M $ whitehat payout
link
Project: Optimism
Date: 02/02/22
Blockchain: OPTIMISM + METIS
Problem: Selfdestuct doesn't subtract value from the contract.
Optimism is a L2 blockchain. It has it's own EVM which is called OVM - a fork with slight changes.
Optimism modified Geth to apply patches to StateDB to store the native balances in an ERC-20 token storage state. ETH is still represented internally as an ERC-20 token OVM_ETH. It's crucial to understand, that under the hood native balance of tokens is represented in ERC-20, it's also important to understand that since Optimism is a fork it's still has stateObject which represents ETH value and equals to the OVM_ETH.
Solidity compiler has interesting feature: selfdestruct(address) method, which is used for destroying all bytecode from the calling contract address and transfering all Ether held to the target address allows interacting with the destructed contract after the opcode invocation, if called in the same transaction.
The issue in Optimism was that with setting the balance of an account after selfdestruct to 0:
stateObject.data.Balance = new(big.Int)
Optimism client sets the balance to zero directly on the stateObject instead of ERC-20 OVM_ETH contract.
The Hacker could:
1) Creates an exploit contract that contains two internal functions. One with selfdestruct, and a second that withdraws the balance of the contract to the caller. The function with selfdestruct sends the contract’s balance to itself. In this case the contract will double its ERC-20 balance of native token.
2) The attacker deploys the contracts and in the constructor executes calls to the selfdestruct function multiple times in a for loop.
3) After the for loop is finished, the constructor calls the second internal function of the exploit contract to transfer the inflated funds to the attacker.
4) The exploit contract is destroyed at the end of the transaction, hacker takes all the profit.
Discoverer: Saurik
Harm: > 1 B $, 2 M $ whitehat payout
link