ETH Price: $2,424.05 (+0.17%)

Transaction Decoder

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 Code
0x016474F8...9194f9C26 0.44 Eth0.46 Eth0.02
0x42D69871...3AA5Ac59a
0.60862122716103473 Eth
Nonce: 19
0.58837434716103473 Eth
Nonce: 20
0.02024688
(MiningPoolHub: Old Address)
2,709.270653781446069512 Eth2,709.270900661446069512 Eth0.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"}}