Transaction Hash:
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 | ||
|---|---|---|---|---|---|
|
0xAA5c4244...ba1aCF05E
Miner
| 13,756.711751679747148158 Eth | 13,756.711798444947148158 Eth | 0.0000467652 | ||
| 0xcCdA5213...8636b1e51 | |||||
| 0xfd774Ce4...311b62824 |
0.021147598 Eth
Nonce: 344
|
0.0211008328 Eth
Nonce: 345
| 0.0000467652 |
Execution Trace
[game (ln:107)]
play_game[game (ln:109)]compare[game (ln:137)]transfer[game (ln:142)]Arina_amount[game (ln:145)]level_judgment[game (ln:320)]balanceOf[game (ln:261)]revert[game (ln:277)]
Arina_judgment[game (ln:321)]balanceOf[game (ln:218)]revert[game (ln:257)]
Arina_amount_judgment[game (ln:322)]revert[game (ln:316)]
transfer[game (ln:147)]transfer[game (ln:148)]transfer[game (ln:149)]revert[game (ln:159)]balanceOf[game (ln:161)]balanceOf[game (ln:161)]Play_game[game (ln:166)]Random[game (ln:167)]level_judgment[game (ln:172)]balanceOf[game (ln:261)]revert[game (ln:277)]
eth_amount_judgment[game (ln:173)]revert[game (ln:296)]
transfer[game (ln:175)]transfer[game (ln:178)]
File 1 of 3: game
File 2 of 3: TokenERC20
File 3 of 3: Token
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];
}
}