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