Guessing Game

  • Build a Failr, Oracle-Free(no oracles allowed) Guessing Game in solidity which pits two players against each other in a game where each player tries to guess whether a randomly generated number is high or low.

    • answer

      /**
      ### reference
      - random optimize
          - https://www.cnblogs.com/huahuayu/p/8884165.html
          - https://blog.csdn.net/weixin_43587332/article/details/        106743233
      - multi people
      **/
      
      pragma solidity ^0.4.0;
      
      library SafeMath {
          function mul(uint256 a, uint256 b) internal pure returns        (uint256) {
              if (a == 0) {
                  return 0;
              }
              uint256 c = a * b;
              assert(c / a == b);
              return c;
          }
      
          function div(uint256 a, uint256 b) internal pure returns        (uint256) {
              // assert(b > 0); // Solidity automatically throws  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;
          }
      
          function sub(uint256 a, uint256 b) internal pure returns        (uint256) {
              assert(b <= a);
              return a - b;
          }
      
          function add(uint256 a, uint256 b) internal pure returns        (uint256) {
              uint256 c = a + b;
              assert(c >= a);
              return c;
          }
      }
      
      
      contract GuessData {
          //address public implementation;
          mapping(address=>uint256) public player2balance;
          address[2] public playerSet;
          uint256[2] inputs;
          address public lastRoundWinner;
      
          uint256 public wager = 0;
          address public playerA = address(0);
          address public playerB = address(0);
          bool public isGameStarted = false;
      }
      
      contract GuessGame is GuessData {
          using SafeMath for uint256;
      
          modifier onlyPlayer() {
              require(playerSet[0] != address(0) && playerSet[1] !=       address(0));
              require(msg.sender == playerSet[0] || msg.sender ==         playerSet[1]);
              _;
          }
      
          function registerPlayer(address player) {
              if (playerSet[0] == address(0)) {
                  playerSet[0] = player;
              } else if (playerSet[1] == address(0)) {
                  playerSet[1] = player;
              } else {
                  revert("player is enough");
              }
          }
      
          function deposit() external payable {
              player2balance[msg.sender] = player2balance[msg.sender].    add (msg.value);
          }
      
          function beginGame(uint256 _wager, uint256 input) external      onlyPlayer payable {
              require(isGameStarted == false);
              require(player2balance[msg.sender] >= _wager);
              wager = _wager;
              inputs[0] = input;
              playerA = msg.sender;
              isGameStarted = true;
          }
      
          function reciveOffer(uint256 input) external onlyPlayer     payable     {
              require(isGameStarted == true);
              require(player2balance[msg.sender] >= wager);
              inputs[1] = input;
              playerB = msg.sender;
          }
      
          function endGame(uint256) external onlyPlayer payable {
              require(isGameStarted == true);
      
              //generate random
              int256 average = 1 << 255 - 1;
              int256 random;
              address winner;
              address loser;
              random = int256(sha256(abi.encodePacked(block.  timestamp,    block.difficulty, inputs[0], inputs[1])));
              random = int256(sha256(abi.encodePacked(random)));
              if (random > average) {
                  winner = playerA;
                  loser = playerB;
              } else {
                  winner = playerB;
                  loser = playerA;
              }
      
              player2balance[loser] = player2balance[loser].sub(wager)    ;
              player2balance[winner] = player2balance[winner].add (wager);
              lastRoundWinner = winner;
              clearData();
          }
      
          function stopGame() external onlyPlayer payable {
              require(isGameStarted == true);
              clearData();
          }
      
          function clearData() internal {
              isGameStarted = false;
              inputs[0] = 0;
              inputs[1] = 0;
              playerA = address(0);
              playerB = address (0);
              wager = 0;
          }
      
          function withdraw(uint256 amount) external onlyPlayer   payable {
              require(isGameStarted == false);
              require(player2balance[msg.sender] >= amount);
              address(this).transfer(amount);
          }
      
          function() external payable {
          }
      }
      
      //contract Proxy is GuessData {
      //    modifier onlyOwner() {require(msg.sender == owner); _;}
      //
      //    constructor() public {
      //        owner = msg.sender;
      //    }
      //
      //    function upgradeTo(address _newImplementation) external       onlyOwner {
      //        require(implementation != _newImplementation);
      //        _setImplementation(_newImplementation);
      //
      //    }
      //
      //    function () payable public {
      //        address imp1 = implementation;
      //        require(imp1 != address(0));
      //        assembly {
      //            let ptr := mload(0x40)
      //            calldatacopy(ptr, 0, calldatasize)
      //            let result := delegatecall(gas, imp1, ptr,        calldatasize, 0, 0)
      //            let size := returndatasize
      //            returndatacopy(ptr, 0, size)
      //            switch result
      //            case 0 {revert(ptr, size)}
      //            default {return(ptr, size)}
      //        }
      //    }
      //
      //    function _setImplementation(address _newImp) internal {
      //        implementation = _newImp;
      //    }
      //}
      //
      
    • run this solidity by brownie

      GuessGame.deploy({'from': accounts[0]})
      
      GuessGame[0].deposit({'from':accounts[1], 'amount':3000000000000000000})
      
      GuessGame[0].deposit({'from':accounts[2], 'amount':2000000000000000000})
      
      GuessGame[0].player2balance(accounts[1])
      
      GuessGame[0].player2balance(accounts[2])
      
      GuessGame[0].registerPlayer(accounts[1], {'from':accounts[0]})
      
      GuessGame[0].registerPlayer(accounts[2], {'from':accounts[0]})
      
      GuessGame[0].beginGame(500000000000000000, 12, {'from': accounts[1]}        )
      
      GuessGame[0].reciveOffer(34, {'from': accounts[2]})
      
      GuessGame[0].endGame(34, {'from': accounts[2]})
      
      GuessGame[0].player2balance(accounts[1])
      
      GuessGame[0].player2balance(accounts[2])
      
      GuessGame[0].isGameStarted()
      
      GuessGame[0].lastRoundWinner()
      

other

proxy:0x3194cBDC3dbcd3E11a07892e7bA5c3394048Cc87

im1: 0x602C71e4DAC47a042Ee7f46E0aee17F94A3bA0B6

accounts[0]: 0x66aB6D9362d4F35596279692F0251Db635165871

owner: accounts[0]

web3.eth.call({'to': '0x3194cBDC3dbcd3E11a07892e7bA5c3394048Cc87', 'data': '3659cfe6000000000000000000000000602c71e4dac47a042ee7f46e0aee17f94a3ba0b6', 'from': '0x66aB6D9362d4F35596279692F0251Db635165871'})


web3.eth.call({'to': '0x3194cBDC3dbcd3E11a07892e7bA5c3394048Cc87', 'data': '5c60da1b000000000000000000000000', 'from': '0x66aB6D9362d4F35596279692F0251Db635165871'})

web3.eth.call({'to': '0x3194cBDC3dbcd3E11a07892e7bA5c3394048Cc87', 'data': '3659cfe6000000000000000000000000602c71e4dac47a042ee7f46e0aee17f94a3ba0b6', 'from': '0x66aB6D9362d4F35596279692F0251Db635165871'})


{
    'implementation': "0x5c60da1b",
    'owner': "0x8da5cb5b"
}