The Ethernaut Level 3: Coin Flip
Introduction to challenge
The Ethernaut is a Web3/Solidity based wargame inspired on overthewire.org, played in the Ethereum Virtual Machine. Each level is a smart contract that needs to be ‘hacked’. The game is 100% open source and all levels are contributions made by other players. Please complete this challenge to better understand the game.
Ethernaut challenge : https://ethernaut.openzeppelin.com/
All Problems
Smart Contract to Hack!!
Task
This is a coin flipping game where you need to build up your winning streak by guessing the outcome of a coin flip. To complete this level you’ll need to use your psychic abilities to guess the correct outcome 10 times in a row.
Things that might help
Check “Beyond the console” in the below link.
https://ethernaut.openzeppelin.com/help
Understanding the Contract
line 21 Here the the contract is getting the hash value of previous block number.
line 28–29 This hash value is divided by some FACTOR(line 14) and based on the answer it is setting the value of side.
Basically, it is trying to get some random number to set the value of side and we need to guess the state of side( using our psychic power) variable consecutively 10 time to hack the contract!!
Things to note
line 23–25 If lastHash is same as blockValue(previous block hash) the transaction would be reverted. This occurs when we try to make 2 transaction on same block.
line 31–37 If by any chance we guessed it wrong the consecutiveWins would be set to 0 and we need to start over again.
Solution
Block number is public information available to all users/contracts of blockchain. We can create an attacker contract(CoinFlipAttacker) that can access the same information from the blockchain and calculate the value of side. Then we’ll call flip() method of our Ethernaut contract with this value. Our guess won’t be wrong as we used same procedure as the CoinFlip.sol .
We’ll be using the Remix IDE to create our attacker contract.
- Open remix ide and create CoinFlip.sol with code mentioned above.
- Create CoinFlipAttacker.sol in remix IDE and paste the below code
line 5 Imported CoinFlip.sol to get instance or our Ethernaut contract.
line 17 Created the instance of CoinFlip with Ethernaut contract address.
You can get your contract address with following line in console. await contract.address
line 33 Called the flip() method of our victim contract.
- Now we need to deploy the contract on Rinkeby TestNet(our Ethernaut contract is present there).
- After deploying we need to call the flip() method of CoinFlipAttacker which will automatically call the CoinFlip’s flip() after calculating the value of side variable from previous block’s hash value.
- We need to call flip() 10 times to complete the task. Remember after successful transaction of flip() we need to wait for few second until the current block is mined on blockchain before calling it again. If you call before that you will get error in Remix IDE.
- In between we can check the value of consecutiveWins in CoinFlip contract by following line in console.
await contract.consecutiveWins()
- Once value of consecutiveWins is 10 you can submit the contract.
Conclusion
Generating random numbers in solidity can be tricky. There currently isn’t a native way to generate them the reason being issue in getting consensus due to random number. Also, everything you use in smart contracts is publicly visible, including the local variables and state variables marked as private by decompiling the bytecode. Miners also have control over things like blockhashes, timestamps, and whether to include certain transactions — which allows them to bias these values in their favor.
To generate Random Value we can use Oracles like Chainlink, which can provide random number through Verifiable Random Function. Learn more about this here.
Hit the 👏(clap) button, it took more time to write this article than to solve the problem😅. Correction of mistake in my understanding is always appreciated in comments.