✅Coin Flip
randomness
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:
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:
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:
We define a constructor like this to feed in the address of the original contract. Deploy the CoinFlipHack
contract:
Once the contract is successfully deployed, click "flip" 10 times to make 10 guesses:
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, 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), RANDAO, or Oraclize).
Last updated