Skip to content

Predict the block hash

pragma solidity ^0.4.21;

contract PredictTheBlockHashChallenge {
  address guesser;
  bytes32 guess;
  uint256 settlementBlockNumber;

  function PredictTheBlockHashChallenge() public payable {
    require(msg.value == 1 ether);
  }

  function isComplete() public view returns (bool) {
    return address(this).balance == 0;
  }

  function lockInGuess(bytes32 hash) public payable {
    require(guesser == 0);
    require(msg.value == 1 ether);

    guesser = msg.sender;
    guess = hash;
    settlementBlockNumber = block.number + 1;
  }

  function settle() public {
    require(msg.sender == guesser);
    require(block.number > settlementBlockNumber);

    bytes32 answer = block.blockhash(settlementBlockNumber);

    guesser = 0;
    if (guess == answer) {
      msg.sender.transfer(2 ether);
    }
  }
}

Goal

Guess the number to win and get all the ETH from the smart contract

Exploit

The following function from the smart contract can be exploited:

  bytes32 answer = block.blockhash(settlementBlockNumber);

The reason why this line of code is vulnerable is because blockhash function (which gives us the hash of the given block) only works for 256 most recent blocks, otherwise it returns 0.

To exploit the contract we need to:

  1. call lockInGuess with "0x0000000000000000000000000000000000000000000000000000000000000000" as argument for the bytes32 hash parameter
  2. wait for more than 256 blocks to be mined
  3. call settle()