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)))
Blockhash
is 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