ETH Price: $2,066.11 (-4.20%)

Transaction Decoder

Block:
7971033 at Jun-16-2019 06:00:14 PM +UTC
Transaction Fee:
0.0000467652 ETH $0.10
Gas Used:
38,971 Gas / 1.2 Gwei

Emitted Events:

38 game.Play_game( from=[Sender] 0xfd774ce4772312b0ad5a2d57358f924311b62824, player=1, comp=1, record=1 )
39 game.Random( from=[Sender] 0xfd774ce4772312b0ad5a2d57358f924311b62824, random_player=586230, random_lottery=692838 )

Account State Difference:

  Address   Before After State Difference Code
13,756.711751679747148158 Eth13,756.711798444947148158 Eth0.0000467652
0xcCdA5213...8636b1e51
0xfd774Ce4...311b62824
0.021147598 Eth
Nonce: 344
0.0211008328 Eth
Nonce: 345
0.0000467652

Execution Trace

game.CALL( )
  • TokenERC20.balanceOf( 0xcCdA5213d453388fB5fB43054BC261c8636b1e51 ) => ( 6861200000000000 )
  • Token.balanceOf( _owner=0xcCdA5213d453388fB5fB43054BC261c8636b1e51 ) => ( balance=20880600000000000000000000 )
    File 1 of 3: game
    pragma solidity ^0.4.25;
    
    //2018.12.03
    
    /////設定管理者/////
    
    contract owned {
        address public owner;
    
        constructor() public{
            owner = msg.sender;
        }
        modifier onlyOwner{
            require(msg.sender == owner);
            _;
        }
        function transferOwnership(address newOwner) public onlyOwner {
            owner = newOwner;
        }
    }
    
    contract ERC20Basic {
      uint256 public totalSupply;
      function balanceOf(address who) public constant returns (uint256);
      function transfer(address to, uint256 value) public returns(bool);
    }
    
    /////遊戲合約/////
    
    contract game is owned{
    
    //初始設定
        
        bool public stop = false;
        
        address public tokenAddress_GIC = 0x340e85491c5F581360811d0cE5CC7476c72900Ba;
        address public tokenAddress_Arina = 0xE6987CD613Dfda0995A95b3E6acBAbECecd41376;
        
        address public address_A = 0xcC22f3Bd8c684463c0Ed6659a001AA62e0a7A146;
        address public address_B = 0xb0D63Fcfb2101C8a1B9b2f0Ff96A13CfEA1A2E65;
    
        mapping (address => uint) readyTime;
        uint public airdrop_GIC = 25*10**18 ;  //酷紅幣為18位小數
        uint public airdrop_Arina = 500*10**8 ;  //Arina幣為6位小數
        
        uint public total_airdrop_GIC = 21000000*10**18; //酷紅幣發送上限為2100萬顆 (小數點18位)
        uint public total_airdrop_Arina = 84000000*10**8; //Arina發送上限為8400萬顆 (小數點6位)
        
        uint public sent_times = 0; //發送次數(初始為零)
        uint public sent_limit = total_airdrop_GIC/airdrop_GIC; //發送幣上限次數
    
        uint public cooldown = 600;  //////冷卻時間(秒)600秒
        uint24 public Probability = 1000000;  /////中獎機率1/1000000
        
        uint random_source = uint(keccak256(msg.sender, block.difficulty, now));
        
        event Play_game(address indexed from, uint8 player, uint8 comp, uint8 record);
        //紀錄遊戲結果
        event Random(address indexed from, uint24 random_player, uint24 random_lottery);
        //記錄兩個亂數
        
    
    //管理權限
        
    
        function stop_game()onlyOwner public{
            stop = true ;
        }
        
        function start_game()onlyOwner public{
            stop = false ;
        }
    
        function set_address_GIC(address new_address)onlyOwner public{
            tokenAddress_GIC = new_address;
        }
        
        function set_address_Arina(address new_address)onlyOwner public{
            tokenAddress_Arina = new_address;
        }
        
        function set_address_A(address new_address)onlyOwner public{
            address_A = new_address;
        }
        
        function set_address_B(address new_address)onlyOwner public{
            address_B = new_address;
        }
    
        function set_cooldown(uint new_cooldown)onlyOwner public{
            cooldown = new_cooldown;
        }
    
        function withdraw_GIC(uint _amount)onlyOwner public{
            require(ERC20Basic(tokenAddress_GIC).transfer(owner, _amount*10**18));
        }
        
        function withdraw_Arina(uint _amount)onlyOwner public{
            require(ERC20Basic(tokenAddress_Arina).transfer(owner, _amount*10**8));
        }
        
        function withdraw_eth()onlyOwner public{
            owner.transfer(address(this).balance);
        }
    
    //來猜拳!!!
        function () payable public{
            if (msg.value == 0){
            play_game(0);
            }
        }
    
        function play_paper()public{
            play_game(0);
        }
    
        function play_scissors()public{
            play_game(1);
        }
    
        function play_stone()public{
            play_game(2);
        }
    
        function play_game(uint8 player) internal{
            require(stop == false);
            
            require(readyTime[msg.sender] < block.timestamp);
            require(player <= 2);
            
            require(sent_times <= sent_limit);
            //檢查遊戲次數未小於限制次數
            
            random_source += 1;
    
            uint8 comp=uint8(uint(keccak256(random_source, block.difficulty, block.timestamp))%3);
            uint8 result = compare(player, comp);
            
    
            if (result == 2){ //玩家贏
                sent_times +=1 ;
                require(ERC20Basic(tokenAddress_GIC).transfer(msg.sender, airdrop_GIC));
                
                (uint _player_amount,uint addressA_amount, uint addressB_amount)
                 = Arina_amount();
                 
                require(ERC20Basic(tokenAddress_Arina).transfer(msg.sender, _player_amount));
                require(ERC20Basic(tokenAddress_Arina).transfer(address_A , addressA_amount));
                require(ERC20Basic(tokenAddress_Arina).transfer(address_B, addressB_amount));
            }
            
            else if(result == 1){ //平手
            }
            
            else if(result == 0){ //玩家輸
                readyTime[msg.sender] = block.timestamp + cooldown;
            }
            
            else revert();
            
            uint bal = ERC20Basic(tokenAddress_GIC).balanceOf(this) + ERC20Basic(tokenAddress_Arina).balanceOf(this);
            
            uint24 random_player = uint24(keccak256(msg.sender, now, random_source))%Probability;
            uint24 random_lottery = uint24(keccak256(random_source, block.difficulty, bal))%Probability;
            
            emit Play_game(msg.sender, player, comp, result);
            emit Random(msg.sender, random_player, random_lottery);
            
            //0-999999的亂數
            
            if (random_player == random_lottery){
                uint8 _level = level_judgment(msg.sender);
                uint _eth = eth_amount_judgment(_level);
                if (address(this).balance >= _eth){
                    msg.sender.transfer(_eth);
                }
                else{
                    msg.sender.transfer(address(this).balance);
                }
                
                //中獎的話傳送eth
            }
            
        }
    
    //判斷用function
    
        function compare(uint8 _player,uint _comp) pure internal returns(uint8 result){
            // input     0 => 布   1 => 剪刀   2 => 石頭
            // output    0 => 輸   1 => 平手   2 => 贏
            uint8 _result;
    
            if (_player==0 && _comp==2){  //布贏石頭 (玩家贏)
                _result = 2;
            }
    
            else if(_player==2 && _comp==0){ //石頭輸布(玩家輸)
                _result = 0;
            }
    
            else if(_player == _comp){ //平手
                _result = 1;
            }
    
            else{
                if (_player > _comp){ //玩家贏 (玩家贏)
                    _result = 2;
                }
                else{ //玩家輸
                    _result = 0;
                }
            }
            return _result;
        }
    
    
        function Arina_judgment() view public returns(uint _amount){
            uint Arina_totBalance = ERC20Basic(tokenAddress_Arina).balanceOf(this);
            if (Arina_totBalance >= total_airdrop_Arina/2){
                return airdrop_Arina;
            }
            else if(total_airdrop_Arina/2 > Arina_totBalance
            && Arina_totBalance >= total_airdrop_Arina/4){
                return airdrop_Arina/2;
            }
            else if(total_airdrop_Arina/4 > Arina_totBalance
            && Arina_totBalance >= total_airdrop_Arina/8){
                return airdrop_Arina/4;
            }
            else if(total_airdrop_Arina/8 > Arina_totBalance
            && Arina_totBalance >= total_airdrop_Arina/16){
                return airdrop_Arina/8;
            }
            else if(total_airdrop_Arina/16 > Arina_totBalance
            && Arina_totBalance >= total_airdrop_Arina/32){
                return airdrop_Arina/16;
            }
            else if(total_airdrop_Arina/32 > Arina_totBalance
            && Arina_totBalance >= total_airdrop_Arina/64){
                return airdrop_Arina/32;
            }
            else if(total_airdrop_Arina/64 > Arina_totBalance
            && Arina_totBalance >= total_airdrop_Arina/128){
                return airdrop_Arina/64;
            }
            else if(total_airdrop_Arina/128 > Arina_totBalance
            && Arina_totBalance >= total_airdrop_Arina/256){
                return airdrop_Arina/128;
            }
            else if(total_airdrop_Arina/256 > Arina_totBalance
            && Arina_totBalance >= total_airdrop_Arina/512){
                return airdrop_Arina/256;
            }
            else if(total_airdrop_Arina/512 > Arina_totBalance){
                return airdrop_Arina/512;
            }
            else revert();
        }
        
        function level_judgment(address _address) view public returns(uint8 _level){
            uint GIC_balance = ERC20Basic(tokenAddress_GIC).balanceOf(_address);
            if (GIC_balance <= 1000*10**18){
                return 1;
            }
            else if(1000*10**18 < GIC_balance && GIC_balance <=10000*10**18){
                return 2;
            }
            else if(10000*10**18 < GIC_balance && GIC_balance <=100000*10**18){
                return 3;
            }
            else if(100000*10**18 < GIC_balance && GIC_balance <=500000*10**18){
                return 4;
            }
            else if(500000*10**18 < GIC_balance){
                return 5;
            }
            else revert();
        }
        
        function eth_amount_judgment(uint8 _level) pure public returns(uint _eth){
            if (_level == 1){
                return 1 ether;
            }
            else if (_level == 2){
                return 3 ether;
            }
            else if (_level == 3){
                return 5 ether;
            }
            else if (_level == 4){
                return 10 ether;
            }
            else if (_level == 5){
                return 20 ether;
            }
            else revert();
        }
        
        function Arina_amount_judgment(uint8 _level, uint _Arina) 
        pure public returns(uint _player, uint _addressA, uint _addressB){
            if (_level == 1){
                return (_Arina*5/10, _Arina*1/10, _Arina*4/10);
            }
            else if (_level == 2){
                return (_Arina*6/10, _Arina*1/10, _Arina*3/10);
            }
            else if (_level == 3){
                return (_Arina*7/10, _Arina*1/10, _Arina*2/10);
            }
            else if (_level == 4){
                return (_Arina*8/10, _Arina*1/10, _Arina*1/10);
            }
            else if (_level == 5){
                return (_Arina*9/10, _Arina*1/10, 0);
            }
            else revert();
        }
        
        function Arina_amount() view public returns(uint _player, uint _addressA, uint _addressB){
            uint8 _level = level_judgment(msg.sender);
            uint _amount = Arina_judgment();
            return Arina_amount_judgment(_level, _amount);
        }
        
        function Arina_balance() view public returns(uint _balance){
            return ERC20Basic(tokenAddress_Arina).balanceOf(this);
        }
    
    
    //查詢
        
        function view_readyTime(address _address) view public returns(uint _readyTime){
            if (block.timestamp >= readyTime[_address]){
                return 0 ;
            }
            else{
                return readyTime[_address] - block.timestamp ;
            }
        }
        function self_readyTime() view public returns(uint _readyTime){
            return view_readyTime(msg.sender);
        }
    
    }

    File 2 of 3: TokenERC20
    pragma solidity >=0.4.22 <0.6.0;
    
    interface tokenRecipient { 
        function receiveApproval(address _from, uint256 _value, address _token, bytes calldata _extraData) external; 
    }
    
    contract TokenERC20 {
        // Public variables of the token
        string public name;
        string public symbol;
        uint8 public decimals = 8;
        // 18 decimals is the strongly suggested default, avoid changing it
        uint256 public totalSupply;
    
        // This creates an array with all balances
        mapping (address => uint256) public balanceOf;
        mapping (address => mapping (address => uint256)) public allowance;
    
        // This generates a public event on the blockchain that will notify clients
        event Transfer(address indexed from, address indexed to, uint256 value);
        
        // This generates a public event on the blockchain that will notify clients
        event Approval(address indexed _owner, address indexed _spender, uint256 _value);
    
        // This notifies clients about the amount burnt
        event Burn(address indexed from, uint256 value);
    
        /**
         * Constructor function
         *
         * Initializes contract with initial supply tokens to the creator of the contract
         */
        constructor() public {
            totalSupply = 84000000 * 10 ** uint256(decimals);  // Update total supply with the decimal amount
            balanceOf[msg.sender] = totalSupply;                // Give the creator all initial tokens
            name = "Arina";                                   // Set the name for display purposes
            symbol = "Arina";                               // Set the symbol for display purposes
        }
    
        /**
         * Internal transfer, only can be called by this contract
         */
        function _transfer(address _from, address _to, uint _value) internal {
            // Prevent transfer to 0x0 address. Use burn() instead
            require(_to != address(0x0));
            // Check if the sender has enough
            require(balanceOf[_from] >= _value);
            // Check for overflows
            require(balanceOf[_to] + _value >= balanceOf[_to]);
            // Save this for an assertion in the future
            uint previousBalances = balanceOf[_from] + balanceOf[_to];
            // Subtract from the sender
            balanceOf[_from] -= _value;
            // Add the same to the recipient
            balanceOf[_to] += _value;
            emit Transfer(_from, _to, _value);
            // Asserts are used to use static analysis to find bugs in your code. They should never fail
            assert(balanceOf[_from] + balanceOf[_to] == previousBalances);
        }
    
        /**
         * Transfer tokens
         *
         * Send `_value` tokens to `_to` from your account
         *
         * @param _to The address of the recipient
         * @param _value the amount to send
         */
        function transfer(address _to, uint256 _value) public returns (bool success) {
            _transfer(msg.sender, _to, _value);
            return true;
        }
    
        /**
         * Transfer tokens from other address
         *
         * Send `_value` tokens to `_to` on behalf of `_from`
         *
         * @param _from The address of the sender
         * @param _to The address of the recipient
         * @param _value the amount to send
         */
        function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
            require(_value <= allowance[_from][msg.sender]);     // Check allowance
            allowance[_from][msg.sender] -= _value;
            _transfer(_from, _to, _value);
            return true;
        }
    
        /**
         * Set allowance for other address
         *
         * Allows `_spender` to spend no more than `_value` tokens on your behalf
         *
         * @param _spender The address authorized to spend
         * @param _value the max amount they can spend
         */
        function approve(address _spender, uint256 _value) public
            returns (bool success) {
            allowance[msg.sender][_spender] = _value;
            emit Approval(msg.sender, _spender, _value);
            return true;
        }
    
        /**
         * Set allowance for other address and notify
         *
         * Allows `_spender` to spend no more than `_value` tokens on your behalf, and then ping the contract about it
         *
         * @param _spender The address authorized to spend
         * @param _value the max amount they can spend
         * @param _extraData some extra information to send to the approved contract
         */
        function approveAndCall(address _spender, uint256 _value, bytes memory _extraData)
            public
            returns (bool success) {
            tokenRecipient spender = tokenRecipient(_spender);
            if (approve(_spender, _value)) {
                spender.receiveApproval(msg.sender, _value, address(this), _extraData);
                return true;
            }
        }
    
        /**
         * Destroy tokens
         *
         * Remove `_value` tokens from the system irreversibly
         *
         * @param _value the amount of money to burn
         */
        function burn(uint256 _value) public returns (bool success) {
            require(balanceOf[msg.sender] >= _value);   // Check if the sender has enough
            balanceOf[msg.sender] -= _value;            // Subtract from the sender
            totalSupply -= _value;                      // Updates totalSupply
            emit Burn(msg.sender, _value);
            return true;
        }
    
        /**
         * Destroy tokens from other account
         *
         * Remove `_value` tokens from the system irreversibly on behalf of `_from`.
         *
         * @param _from the address of the sender
         * @param _value the amount of money to burn
         */
        function burnFrom(address _from, uint256 _value) public returns (bool success) {
            require(balanceOf[_from] >= _value);                // Check if the targeted balance is enough
            require(_value <= allowance[_from][msg.sender]);    // Check allowance
            balanceOf[_from] -= _value;                         // Subtract from the targeted balance
            allowance[_from][msg.sender] -= _value;             // Subtract from the sender's allowance
            totalSupply -= _value;                              // Update totalSupply
            emit Burn(_from, _value);
            return true;
        }
    }

    File 3 of 3: Token
    pragma solidity ^0.4.11;
     
    contract Token {
        string public symbol = "";
        string public name = "";
        uint8 public constant decimals = 18;
        uint256 _totalSupply = 0;
        address owner = 0;
        bool setupDone = false;
       
        event Transfer(address indexed _from, address indexed _to, uint256 _value);
        event Approval(address indexed _owner, address indexed _spender, uint256 _value);
     
        mapping(address => uint256) balances;
     
        mapping(address => mapping (address => uint256)) allowed;
     
        function Token(address adr) {
            owner = adr;        
        }
       
        function SetupToken(string tokenName, string tokenSymbol, uint256 tokenSupply)
        {
            if (msg.sender == owner && setupDone == false)
            {
                symbol = tokenSymbol;
                name = tokenName;
                _totalSupply = tokenSupply * 1000000000000000000;
                balances[owner] = _totalSupply;
                setupDone = true;
            }
        }
     
        function totalSupply() constant returns (uint256 totalSupply) {        
            return _totalSupply;
        }
     
        function balanceOf(address _owner) constant returns (uint256 balance) {
            return balances[_owner];
        }
     
        function transfer(address _to, uint256 _amount) returns (bool success) {
            if (balances[msg.sender] >= _amount
                && _amount > 0
                && balances[_to] + _amount > balances[_to]) {
                balances[msg.sender] -= _amount;
                balances[_to] += _amount;
                Transfer(msg.sender, _to, _amount);
                return true;
            } else {
                return false;
            }
        }
     
        function transferFrom(
            address _from,
            address _to,
            uint256 _amount
        ) returns (bool success) {
            if (balances[_from] >= _amount
                && allowed[_from][msg.sender] >= _amount
                && _amount > 0
                && balances[_to] + _amount > balances[_to]) {
                balances[_from] -= _amount;
                allowed[_from][msg.sender] -= _amount;
                balances[_to] += _amount;
                Transfer(_from, _to, _amount);
                return true;
            } else {
                return false;
            }
        }
     
        function approve(address _spender, uint256 _amount) returns (bool success) {
            allowed[msg.sender][_spender] = _amount;
            Approval(msg.sender, _spender, _amount);
            return true;
        }
     
        function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
            return allowed[_owner][_spender];
        }
    }