diff --git a/_posts/2024-11-26-SECCON-CTF-13-Quals-Blockchain-Writeup.md b/_posts/2024-11-26-SECCON-CTF-13-Quals-Blockchain-Writeup.md index 034092c988..b4f76bbacc 100644 --- a/_posts/2024-11-26-SECCON-CTF-13-Quals-Blockchain-Writeup.md +++ b/_posts/2024-11-26-SECCON-CTF-13-Quals-Blockchain-Writeup.md @@ -60,6 +60,7 @@ contract TrillionEther { } } ``` +
The most apparent bug exists in the _newWallet function, where an uninitialized storage variables bug occurs. The wallet variable is declared as storage but is not properly initialized before assignment. Consequently, the data is written starting from storage slot 0. @@ -71,6 +72,7 @@ function _newWallet(bytes32 name, uint256 balance, address owner) internal retur wallet.owner = owner; } ``` +
In the TrillionEther contract, storage slot 0 holds the wallets array. Being a dynamic array, this slot stores the array’s length, and the actual elements are stored starting from keccak(0). @@ -80,6 +82,7 @@ $ forge inspect TrillionEther storage-layout --pretty |---------|-------------------------------|------|--------|-------|-------------------------------------| | wallets | struct TrillionEther.Wallet[] | 0 | 0 | 32 | src/TrillionEther.sol:TrillionEther | ``` +
The wallets array consists of the Wallet struct, which occupies three storage slots for each element: ```solidity @@ -91,6 +94,7 @@ struct Wallet { Wallet[] public wallets; ``` +
As a result, the storage slot for a new element in the array can be calculated using the formula: `keccak(0) + arrayLength * 3`