ETH Price: $2,515.12 (+0.15%)

Transaction Decoder

Block:
9811342 at Apr-05-2020 09:51:13 AM +UTC
Transaction Fee:
0.00013816 ETH $0.35
Gas Used:
27,632 Gas / 5 Gwei

Emitted Events:

80 CryptoGames.DemoGame( player=[Sender] 0x85ef8b386f8c3303578cc0522738a9bc85d564ae, seed=5637552C1F09AE7DC36A487110F52A1119D403ADE1527BB439DCB19571BB917E, bet=770000000000000000, choice=0x01, game=KNB )

Account State Difference:

  Address   Before After State Difference Code
(zhizhu.top)
685.722385647113132573 Eth685.722523807113132573 Eth0.00013816
0x85eF8b38...C85D564ae
0.001 Eth
Nonce: 0
0.00086184 Eth
Nonce: 1
0.00013816

Execution Trace

CryptoGames.demo_game( game=KNB, _choice=0x01, seed=5637552C1F09AE7DC36A487110F52A1119D403ADE1527BB439DCB19571BB917E, bet=770000000000000000 )
// ╔══╗╔═══╗╔╗╔╗╔═══╗╔════╗╔══╗╔═══╗╔══╗╔╗──╔╗╔═══╗──╔══╗─╔═══╗╔════╗
// ║╔═╝║╔═╗║║║║║║╔═╗║╚═╗╔═╝║╔╗║║╔══╝║╔╗║║║──║║║╔══╝──║╔╗║─║╔══╝╚═╗╔═╝
// ║║──║╚═╝║║╚╝║║╚═╝║──║║──║║║║║║╔═╗║╚╝║║╚╗╔╝║║╚══╗──║╚╝╚╗║╚══╗──║║
// ║║──║╔╗╔╝╚═╗║║╔══╝──║║──║║║║║║╚╗║║╔╗║║╔╗╔╗║║╔══╝──║╔═╗║║╔══╝──║║
// ║╚═╗║║║║──╔╝║║║─────║║──║╚╝║║╚═╝║║║║║║║╚╝║║║╚══╗╔╗║╚═╝║║╚══╗──║║
// ╚══╝╚╝╚╝──╚═╝╚╝─────╚╝──╚══╝╚═══╝╚╝╚╝╚╝──╚╝╚═══╝╚╝╚═══╝╚═══╝──╚╝


//By playing platform games you agree that your age is over 21 and you clearly understand that you can lose your coins
//The platform is not responsible for all Ethereum cryptocurrency losses during the game.
//The contract uses the entropy algorithm Signidice
//https://github.com/gluk256/misc/blob/master/rng4ethereum/signidice.md

pragma solidity 0.5.16;

library SafeMath {
  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a * b;
    assert(a == 0 || c / a == b);
    return c;
  }

  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a / b;
    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 CryptoGames {
    using SafeMath for uint;
    address payable public  owner = 0x333333e25F2176e2e165Aeb1b933cE10Cf315b47;
    address public  CROUPIER_BOB = 0xB0B3336c83A4c86FBd4f804BB8D410B23F181b05;
    uint public minStake = 0.01 ether;
    uint public maxStake = 15 ether;
    uint public constant WIN_COEFFICIENT = 198;
    uint public constant DICE_COEFFICIENT = 600;
    mapping(address => uint) public deposit;
    mapping(address => uint) public withdrawal;
    bool status = true;

    enum GameState {
        Pending,
        Win,
        Lose,
        Draw
    }
    
    enum Games {
        CoinFlip,
        KNB,
        Dice
    }

    struct Game {
        Games game_title;
        address payable player;
        uint bet;
        bytes32 seed;
        GameState state;
        uint result;
        bytes choice;
        uint profit;
    }

    event NewGame(address indexed player, bytes32 seed, uint bet, bytes choice, string  game);
    event DemoGame(address indexed player, bytes32 seed, uint bet, bytes choice, string  game);
    event ConfirmGame(address indexed player, string  game, uint profit, bytes choice, uint game_choice, bytes32 seed, bool status, bool draw,  uint timestamp);
    event Deposit(address indexed from, uint indexed block, uint value, uint time);
    event Withdrawal(address indexed from, uint indexed block, uint value, uint ident,uint time);
    mapping(bytes32 => Game) public listGames;
    
    // Only our croupier and no one else can open the bet
    modifier onlyCroupier() {
        require(msg.sender == CROUPIER_BOB);
        _;
    }
    
    // Check that the rate is between 0.01 - 15 ether
    modifier betInRange() {
        require(minStake <= msg.value && msg.value <= maxStake);
        _;
    }
    
    modifier onlyOwner {
        require(msg.sender == owner); _;
    }
    
    modifier isNotContract() {
        uint size;
        address addr = msg.sender;
        assembly { size := extcodesize(addr) }
        require(size == 0 && tx.origin == msg.sender);
        _;
    }
    
    modifier contractIsOn() {
        require(status);
        _;
    }

    // Game CoinFlip
    // The game of tossing a coin, the coin has 2 sides,
    // an eagle and a tails, which one is up to you to choose
    function game_coin(bytes memory _choice, bytes32 seed) public betInRange payable returns(uint8) {
        string memory game_title = 'CoinFlip';
        uint8 user_choice;
        assembly {user_choice := mload(add(0x1, _choice))}
        require(listGames[seed].bet == 0x0);
        require(_choice.length == 1);
        require(user_choice == 0 || user_choice == 1);
        
        listGames[seed] = Game({
            game_title: Games.CoinFlip,
            player: msg.sender,
            bet: msg.value,
            seed: seed,
            state: GameState.Pending,
            choice: _choice,
            result: 0,
            profit: 0
        });
        emit NewGame(msg.sender, seed, msg.value, _choice, game_title);
        return user_choice;
    }
    
    // Game KNB
    // Game of stone, scissors, paper
    // The stone breaks the scissors, the scissors cut the paper, the paper wraps the stone.
    // Everything is just kk in childhood, it remains only to try to play
    function game_knb(bytes memory _choice, bytes32 seed) public betInRange payable {
        string memory game_title = 'KNB';
        uint8 user_choice;
        assembly {user_choice := mload(add(0x1, _choice))}
        require(listGames[seed].bet == 0x0);
        require(_choice.length == 1);
        //Checking that bids are in the right range
        //1 - stone, 2 - scissors, 3 - paper
        require(user_choice >=1 && user_choice <=3);
        
        listGames[seed] = Game({
            game_title: Games.KNB,
            player: msg.sender,
            bet: msg.value,
            seed: seed,
            state: GameState.Pending,
            choice: _choice,
            result: 0,
            profit: 0
        });
       emit NewGame(msg.sender, seed, msg.value, _choice, game_title);
    }
    
    // Game Dice
    // Playing dice, the player can select up to 5 dice values at a time. The more dice a player chooses, the less his final reward.
    // The reward is calculated according to the formula:  (6 / number of selected cubes) * bet
    function game_dice(bytes memory _choice, bytes32 seed) public betInRange payable {
        string memory game_title = 'Dice';
        require(listGames[seed].bet == 0x0);
        //Checking that bids are in the right range, and no more than 5 cubes are selected
        require(_choice.length >= 1 && _choice.length <= 5);
        
        // for(uint i=0; i< _choice.length; i++){
        //     require(_choice[i] > 0 && _choice[i] < 7);
        // }
        
        listGames[seed] = Game({
            game_title: Games.Dice,
            player: msg.sender,
            bet: msg.value,
            seed: seed,
            state: GameState.Pending,
            choice: _choice,
            result: 0,
            profit: 0
        });
        emit NewGame(msg.sender, seed, msg.value, _choice, game_title);
    }

    //Casino must sign the resulting value V with its PrivKey, thus producing the digital signature S = sign(PrivKey, V), and send the corresponding TX, containing S.
    //The contract recovers the actual public key (K) from the digital signature S, and verifies that it is equal to the previously published PubKey (K == PubKey).
    //If APK does not match PubKey, it is tantamount to cheating. In this case, the contract simply rejects the transaction.
    //The contract uses S as a seed for the predefined PRNG algorithm (e.g. SHA-3 based), which produces the lucky number (L), e.g. between 1 and 6.
    function confirm(bytes32 seed, uint8 _v, bytes32 _r, bytes32 _s) public onlyCroupier {
        // Checking that it was Uncle Bob who signed the transaction, otherwise we reject the impostor transaction
        require (ecrecover(seed, _v, _r, _s) == CROUPIER_BOB);
        Game storage game = listGames[seed];
        bytes memory choice = game.choice;
        game.result = uint256(_s) % 12;
        uint profit = 0;
        uint8 user_choice;
        //Our algorithms are very simple and understandable even to the average Internet user and do not need additional explanation
        //Coin game algorithm
        if (game.game_title == Games.CoinFlip){
            assembly {user_choice := mload(add(0x1, choice))}
            if(game.result == user_choice){
                profit = game.bet.mul(WIN_COEFFICIENT).div(100);
                game.state = GameState.Win;
                game.profit = profit;
                game.player.transfer(profit);
                emit ConfirmGame(game.player, 'CoinFlip', profit, game.choice, game.result, game.seed, true, false, now);
            }else{
                game.state = GameState.Lose;
                emit ConfirmGame(game.player, 'CoinFlip', 0, game.choice, game.result, game.seed, false, false, now);
            }
        //KNB game algorithm
        }else if(game.game_title == Games.KNB){
            assembly {user_choice := mload(add(0x1, choice))}
            if(game.result != user_choice){
                if (user_choice == 1 && game.result == 2 || user_choice == 2 && game.result == 3 || user_choice == 3 && game.result == 1) {
                    profit = game.bet.mul(WIN_COEFFICIENT).div(100);
                    game.state = GameState.Win;
                    game.profit = profit;
                    game.player.transfer(profit);
                    emit ConfirmGame(game.player, 'KNB', profit, game.choice, game.result, game.seed, true, false, now);
                }else{
                    game.state = GameState.Lose;
                    emit ConfirmGame(game.player, 'KNB', 0, game.choice, game.result, game.seed, false, false, now);
                }
            }else{
                profit = game.bet.sub(0.001 ether);
                game.player.transfer(profit);
                game.state = GameState.Draw;
                emit ConfirmGame(game.player, 'KNB', profit, game.choice, game.result, game.seed, false, true, now);
            }
        //Dice game algorithm
        }else if(game.game_title == Games.Dice){
            uint length = game.choice.length + 1;
            for(uint8 i=1; i< length; i++){
                assembly {user_choice  := mload(add(i, choice))}
                if (user_choice == game.result){
                    profit = game.bet.mul(DICE_COEFFICIENT.div(game.choice.length)).div(100);
                }
            }
            if(profit > 0){
                game.state = GameState.Win;
                game.profit = profit;
                game.player.transfer(profit);
                emit ConfirmGame(game.player, 'Dice', profit, game.choice, game.result, game.seed, true, false, now);
            }else{
                game.state = GameState.Lose;
                emit ConfirmGame(game.player, 'Dice', 0, game.choice, game.result, game.seed, false, false, now);
            }
        }
    }
    // Demo game, 0 ether value. To reduce the cost of the game, we calculate a random result on the server
    function demo_game(string memory game, bytes memory _choice, bytes32 seed, uint bet) public {
        emit DemoGame(msg.sender, seed, bet, _choice, game);
    }
    
    function get_player_choice(bytes32 seed) public view returns(bytes memory) {
        Game storage game = listGames[seed];
        return game.choice;
    }
    
    //The casino has its own expenses for maintaining the servers, paying for them, each signature by our bot Bob costs 0.00135 ether
    //and we honestly believe that the money that players own is ours, everyone can try their luck and play with us
    function pay_royalty (uint _value) onlyOwner public {
        owner.transfer(_value * 1 ether);
    }
    
    //automatic withdrawal using server bot
    function multisend(address payable[] memory dests, uint256[] memory values, uint256[] memory ident) onlyOwner contractIsOn public returns(uint) {
        uint256 i = 0;
        
        while (i < dests.length) {
            uint transfer_value = values[i].sub(values[i].mul(3).div(100));
            dests[i].transfer(transfer_value);
            withdrawal[dests[i]]+=values[i];
            emit Withdrawal(dests[i], block.number, values[i], ident[i], now);
            i += 1;
        }
        return(i);
    }
    
    function startProphylaxy()onlyOwner public {
        status = false;
    }
    
    function stopProphylaxy()onlyOwner public {
        status = true;
    }
    // recharge function for games
    function() external isNotContract contractIsOn betInRange payable {
        deposit[msg.sender]+= msg.value;
        emit Deposit(msg.sender, block.number, msg.value, now);
    }
}

//P̴̩͖͈̳o̷̡̳̭̞͔̺̩̩w̸̡̡̡̤̹͙͔̜̮̟̺̬̰͔͉͉͎͉̠̝͜ͅe̵̜̤̹ŗ̶̹̞̰̭̹̭̻̤͔͈͓͉ę̵̡͉͚̲̞̘͙̥̳͇͓̭ḑ̷̞̰̯̭͚͎̣͔̜̝̬͜ͅͅ ̵̣̲b̷̢͙͈̣̝̩͔͉͖y̷̢̱̠̙̘̹̟̠̙͖͍̹̦͍ͅ ̵̡̢̠̗͎͍͕̯̹͈͈̬̹c̷̢̪̪͎̺̠̤̮̙̜̞͈̞̝̭̭r̸̥̯̩̩̝̟͉̲̪̣̬̟̮̤̲̜y̵̗̬͓͎̻̱̝̗͕̟͙̯͇̜̤̲͔̭̫͓p̸̢͇͇̠̪t̵̹̳̮͇͜ǫ̸̙̬ͅͅģ̵̹̬͉̫̣͔̝̳̘̰̘̤̮a̸̡͖̮͙̯̬̰̫̫̘͎͎̰͇̹̜̼̥͚͇͉͔͚͓m̸̢̫̙̫̮̪͕̭̟̬̣̟̫̦͙̖ȩ̸̡̧̟̰̯͖̲͍̳͚̘̦͎̙̥̫͎̺̤̮͜ͅ.̴̨̱̲͚b̸͍͔e̶̡̡̡̜̬͓̤̣͍̝͚͖̘͈̱̘̲̠͓͍͙͉̯͍t̵̻̮
//
//