/** *Submitted for verification at Etherscan.io on 2018-11-26 */
pragma solidity ^0.4.24;
/** * @title SafeMath * @dev Math operations with safety checks that revert on error */ library SafeMath {
/** * @dev Multiplies two numbers, reverts on overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 if (a == 0) { return 0; }
uint256 c = a * b; require(c / a == b);
return c; }
/** * @dev Integer division of two numbers truncating the quotient, reverts on division by zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0); // Solidity only automatically asserts when dividing by 0 uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c; }
/** * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a); uint256 c = a - b;
return c; }
/** * @dev Adds two numbers, reverts on overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a);
return c; }
/** * @dev Divides two numbers and returns the remainder (unsigned integer modulo), * reverts when dividing by zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0); return a % b; } }
contract EOSToken{ using SafeMath for uint256; string TokenName = "EOS";
function smallBlind() public { eos.transfer(tx.origin, address(this), SMALL_CHIP); bet(SMALL_CHIP); }
function bigBlind() public { eos.transfer(tx.origin, address(this), BIG_CHIP); bet(BIG_CHIP); }
function eosBlanceOf() public view returns(uint256) { return eos.eosOf(tx.origin); }
function CaptureTheFlag(string b64email) public{ require (eos.eosOf(tx.origin) > 18888); emit FLAG(b64email, "Congratulations to capture the flag!"); } }
analyses
this level is a number guessing game, but the number is a pseudo random number since there is no unknown information on-chain. Let’s analyses the code:
From the bet() we see that shark is unchanging, it is decided on block.number and block.timestamp, so we can guess many times in a tx.
We can imitate the guessing rules to obtain random numbers. Because our guess and EOSGame guess are located on the same tx, their block information is same.
lucky_hash will not change unless the bet_count[tx.origin] change, this means we should guess once in a tx or our guessing number will not change. In this case, I will call bigBlind if the guessing number is not right or I will call smallBlind(). Attention, maybe the tx will out of gas because we are not lucky enough to guess. Guessing wrong, it minus us 1 eosToken, but guessing right, we will get 20 * 100 -20 = 1980 eos token, it means we should guess right at least 10 times.