Transaction Hash:
Block:
9520723 at Feb-20-2020 02:49:02 PM +UTC
Transaction Fee:
0.00024688 ETH
$0.60
Gas Used:
49,376 Gas / 5 Gwei
Emitted Events:
114 |
SnakesAndLadders.LogAddPlayerFunds( sender=[Sender] 0x42d69871dde6671bd3ff31e574ddb633aa5ac59a, amount=20000000000000000 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x016474F8...9194f9C26 | 0.44 Eth | 0.46 Eth | 0.02 | ||
0x42D69871...3AA5Ac59a |
0.60862122716103473 Eth
Nonce: 19
|
0.58837434716103473 Eth
Nonce: 20
| 0.02024688 | ||
0xb2930B35...e543a0347
Miner
| (MiningPoolHub: Old Address) | 2,709.270653781446069512 Eth | 2,709.270900661446069512 Eth | 0.00024688 |
Execution Trace
ETH 0.02
SnakesAndLadders.CALL( )
{"SafeMath.sol":{"content":"pragma solidity ^0.5.0;\n\n/**\n * @dev Wrappers over Solidity\u0027s arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it\u0027s recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity\u0027s `+` operator.\n *\n * Requirements:\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c \u003e= a, \"SafeMath: addition overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity\u0027s `-` operator.\n *\n * Requirements:\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b \u003c= a, \"SafeMath: subtraction overflow\");\n uint256 c = a - b;\n\n return c;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity\u0027s `*` operator.\n *\n * Requirements:\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring \u0027a\u0027 not being zero, but the\n // benefit is lost if \u0027b\u0027 is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers. Reverts on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity\u0027s `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n // Solidity only automatically asserts when dividing by 0\n require(b \u003e 0, \"SafeMath: division by zero\");\n uint256 c = a / b;\n // assert(a == b * c + a % b); // There is no case in which this doesn\u0027t hold\n\n return c;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * Reverts when dividing by zero.\n *\n * Counterpart to Solidity\u0027s `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b != 0, \"SafeMath: modulo by zero\");\n return a % b;\n }\n}\n"},"SnakesAndLadders.sol":{"content":"pragma solidity ^0.5.0;\n\nimport \"./SafeMath.sol\";\n\ncontract SnakesAndLadders {\n using SafeMath for uint;\n using SafeMath for uint8; // 0-255\n\n // All balances\n mapping(address =\u003e uint) public balances;\n uint public totalBalance;\n\n // Payout addresses\n address private payout1;\n address private payout2;\n\n // Board composition\n uint8 constant private tiles = 100;\n mapping(uint8 =\u003e uint8) private boardElements;\n\n // Player: is true if it\u0027s the user, otherwise is the AI\n // Turn: starting from 1\n // Move: the dice move from 1 to 6\n event LogGame(address sender, bool result, int balancediff, uint seed);\n event LogAddPlayerFunds(address sender, uint amount);\n event LogWithdrawPlayerFunds(address sender, uint amount);\n event LogAddFunds(address sender, uint amount);\n event LogPayout(address sender, uint amount);\n\n constructor(address _payout1, address _payout2) public {\n // ladders\n boardElements[4] = 14;\n boardElements[8] = 32;\n boardElements[20] = 38;\n boardElements[28] = 84;\n boardElements[40] = 59;\n boardElements[58] = 83;\n boardElements[72] = 93;\n // snakes\n boardElements[15] = 3;\n boardElements[31] = 9;\n boardElements[44] = 26;\n boardElements[62] = 19;\n boardElements[74] = 70;\n boardElements[85] = 33;\n boardElements[91] = 71;\n boardElements[98] = 80;\n // payouts\n payout1 = _payout1;\n payout2 = _payout2;\n }\n\n /**\n * Avoid sending money directly to the contract\n */\n function () external payable {\n revert(\"Use addPlayerFunds to send money.\");\n }\n\n /**\n * Plays the game\n */\n function play(uint amount) public {\n require(amount \u003e 0, \"You must send something to bet\");\n require(amount \u003c= balances[msg.sender], \"You don\u0027t have enough balance to play\");\n require(amount*5 \u003c address(this).balance - totalBalance, \"You cannot bet more than 1/5 of this contract free balance\");\n require(amount \u003c= 1 ether, \"Maximum bet amount is 1 ether\");\n require(tx.origin == msg.sender, \"Contracts cannot play the game\");\n uint seed = random();\n uint turn = 0;\n // let\u0027s decide who starts\n bool player = false; // true if next move is for player, false if for computer\n uint8 move = randomDice(seed, turn); // move 0 decides who starts\n if (move == 1 || move == 2) {\n player = true;\n }\n // make all the moves and emit the results\n uint8 playerUser = 0;\n uint8 playerAI = 0;\n uint8 boardElement;\n while (playerUser != tiles \u0026\u0026 playerAI != tiles) {\n turn++;\n move = randomDice(seed, turn);\n if (player) {\n playerUser = playerUser + move;\n if (playerUser \u003e tiles) {\n playerUser = tiles - (playerUser - tiles);\n }\n boardElement = boardElements[playerUser];\n if (boardElement != 0) {\n playerUser = boardElement;\n }\n } else {\n playerAI = playerAI + move;\n if (playerAI \u003e tiles) {\n playerAI = tiles - (playerAI - tiles);\n }\n boardElement = boardElements[playerAI];\n if (boardElement != 0) {\n playerAI = boardElement;\n }\n }\n // if the player rolls a 6 has an extra turn\n if (move != 6) {\n player = !player;\n }\n }\n if (playerUser == tiles) {\n balances[msg.sender] += amount;\n totalBalance += amount;\n emit LogGame(msg.sender, true, int(amount), seed);\n } else {\n balances[msg.sender] -= amount;\n totalBalance -= amount;\n emit LogGame(msg.sender, false, -int(amount), seed);\n }\n\n // in case that there are more than 2 ether in the pool generate payout\n if (address(this).balance - totalBalance \u003e= 2 ether) {\n emit LogPayout(msg.sender, 0.4 ether);\n balances[payout1] += 0.2 ether;\n balances[payout2] += 0.2 ether;\n totalBalance += 0.4 ether;\n }\n }\n\n /**\n * Returns a non-miner-secure random uint.\n */\n function random() public view returns(uint) {\n return uint(keccak256(abi.encodePacked(block.timestamp, block.difficulty, msg.sender)));\n }\n\n /**\n * Returns a random number from 1 to 6 based from a uint and turn.\n */\n function randomDice(uint randomString, uint turn) public pure returns(uint8) {\n return uint8(randomString/2**(turn%256))%6 + 1;\n }\n\n /**\n * User adds player funds.\n */\n function addPlayerFunds() public payable {\n require(msg.value \u003e 0, \"You must send something to add into balance\");\n emit LogAddPlayerFunds(msg.sender, msg.value);\n balances[msg.sender] += msg.value;\n totalBalance += msg.value;\n }\n\n /**\n * Withdraw player funds.\n */\n function withdrawPlayerFunds() public {\n uint toWithdraw = balances[msg.sender];\n require(toWithdraw \u003e 0, \"There is no balance to withdraw\");\n require(toWithdraw \u003c= totalBalance, \"There are not enough funds in the contract to withdraw\");\n require(tx.origin == msg.sender, \"Contracts cannot withdraw funds\");\n emit LogWithdrawPlayerFunds(msg.sender, toWithdraw);\n balances[msg.sender] = 0;\n totalBalance -= toWithdraw;\n msg.sender.transfer(toWithdraw);\n }\n\n /**\n * Anyone can send funds but it has to be from this function. This does not count in totalBalance.\n */\n function addFunds() public payable {\n require(msg.value \u003e 0, \"You must send something when calling this function\");\n emit LogAddFunds(msg.sender, msg.value);\n }\n\n /**\n * Only payout addresses can emit payouts.\n */\n function payout(uint amount) public {\n require(msg.sender == payout1 || msg.sender == payout2, \"You must be one a payout address\");\n require(amount \u003e 0, \"The balance that you want to withdraw must be more than 0\");\n require(amount%2 == 0, \"Amount to withdraw must be pair\");\n // this is made in a way to protect the customer\n require(address(this).balance - totalBalance \u003e= amount, \"There is not enough free balance to withdraw\");\n emit LogPayout(msg.sender, amount);\n uint half = amount/2;\n balances[payout1] += half;\n balances[payout2] += half;\n totalBalance += amount;\n }\n}\n"}}