Transaction Hash:
Block:
4902369 at Jan-13-2018 04:10:05 PM +UTC
Transaction Fee:
0.00247344 ETH
$4.66
Gas Used:
82,448 Gas / 30 Gwei
Emitted Events:
61 |
RKCToken.Transfer( from=[Sender] 0x2984581ece53a4390d1f568673cf693139c97049, to=0xfc9D31D749839eFF730e796FD430B4F39E414d2C, value=13000000000000000000 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x2984581e...139C97049 | (Cryptopia 2) |
20.653425831539005809 Eth
Nonce: 132626
|
20.650952391539005809 Eth
Nonce: 132627
| 0.00247344 | |
0x52bc44d5...b7d7bE3b5
Miner
| (Nanopool) | 10,984.723505889204390839 Eth | 10,984.725979329204390839 Eth | 0.00247344 | |
0x6cCB5694...DDFa9b202 |
Execution Trace
RKCToken.transfer( _to=0xfc9D31D749839eFF730e796FD430B4F39E414d2C, _value=13000000000000000000 )
transfer[RKCToken (ln:454)]
updatePremiums[RKCToken (ln:455)]
updatePremiums[RKCToken (ln:456)]
transfer[RKCToken (ln:457)]
// Royal Kingdom Coin Token // www.royalkingdomcoin.com // // RKC token is a virtual token, governed by ERC20-compatible Ethereum Smart Contract and secured by Ethereum Blockchain // The official website is https://www.royalkingdomcoin.com/ // // The uints are all in wei and atto tokens (*10^-18) // The contract code itself, as usual, is at the end, after all the connected libraries pragma solidity ^0.4.11; /** * Math operations with safety checks */ library SafeMath { function mul(uint a, uint b) internal returns (uint) { uint c = a * b; assert(a == 0 || c / a == b); return c; } function div(uint a, uint b) internal returns (uint) { assert(b > 0); uint c = a / b; assert(a == b * c + a % b); return c; } function sub(uint a, uint b) internal returns (uint) { assert(b <= a); return a - b; } function add(uint a, uint b) internal returns (uint) { uint c = a + b; assert(c >= a); return c; } function max64(uint64 a, uint64 b) internal constant returns (uint64) { return a >= b ? a : b; } function min64(uint64 a, uint64 b) internal constant returns (uint64) { return a < b ? a : b; } function max256(uint256 a, uint256 b) internal constant returns (uint256) { return a >= b ? a : b; } function min256(uint256 a, uint256 b) internal constant returns (uint256) { return a < b ? a : b; } function assert(bool assertion) internal { if (!assertion) { throw; } } } /* * ERC20Basic * Simpler version of ERC20 interface * see https://github.com/ethereum/EIPs/issues/20 */ contract ERC20Basic { uint public totalSupply; function balanceOf(address who) constant returns (uint); function transfer(address to, uint value); event Transfer(address indexed from, address indexed to, uint value); } /* * Basic token * Basic version of StandardToken, with no allowances */ contract BasicToken is ERC20Basic { using SafeMath for uint; mapping(address => uint) balances; /* * Fix for the ERC20 short address attack */ modifier onlyPayloadSize(uint size) { if(msg.data.length < size + 4) { throw; } _; } function transfer(address _to, uint _value) onlyPayloadSize(2 * 32) { balances[msg.sender] = balances[msg.sender].sub(_value); balances[_to] = balances[_to].add(_value); Transfer(msg.sender, _to, _value); } function balanceOf(address _owner) constant returns (uint balance) { return balances[_owner]; } } /* * ERC20 interface * see https://github.com/ethereum/EIPs/issues/20 */ contract ERC20 is ERC20Basic { function allowance(address owner, address spender) constant returns (uint); function transferFrom(address from, address to, uint value); function approve(address spender, uint value); event Approval(address indexed owner, address indexed spender, uint value); } /** * Standard ERC20 token * * https://github.com/ethereum/EIPs/issues/20 * Based on code by FirstBlood: * https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol */ contract StandardToken is BasicToken, ERC20 { mapping (address => mapping (address => uint)) allowed; function transferFrom(address _from, address _to, uint _value) { var _allowance = allowed[_from][msg.sender]; // Check is not needed because sub(_allowance, _value) will already throw if this condition is not met // if (_value > _allowance) throw; balances[_to] = balances[_to].add(_value); balances[_from] = balances[_from].sub(_value); allowed[_from][msg.sender] = _allowance.sub(_value); Transfer(_from, _to, _value); } function approve(address _spender, uint _value) { allowed[msg.sender][_spender] = _value; Approval(msg.sender, _spender, _value); } function allowance(address _owner, address _spender) constant returns (uint remaining) { return allowed[_owner][_spender]; } } /* * Ownable * * Base contract with an owner. * Provides onlyOwner modifier, which prevents function from running if it is called by anyone other than the owner. */ contract Ownable { address public owner; function Ownable() { owner = msg.sender; } modifier onlyOwner() { if (msg.sender != owner) { throw; } _; } function transferOwnership(address newOwner) onlyOwner { if (newOwner != address(0)) { owner = newOwner; } } } contract RKCToken is StandardToken, Ownable { using SafeMath for uint; //-------------- Info for ERC20 explorers -----------------// string public name = "Royal Kingdom Coin"; string public symbol = "RKC"; uint public decimals = 18; //--------------------- Constants ------------------------// bool public constant TEST_MODE = false; uint public constant atto = 1000000000000000000; uint public constant INITIAL_SUPPLY = 15000000 * atto; // 15 mln RKC. Impossible to mint more than this address public teamWallet = 0xb79F963f200f85D0e3dD60C82ABB8F80b5869CB9; // Made up ICO address (designating the token pool reserved for ICO, no one has access to it) address public ico_address = 0x1c01C01C01C01c01C01c01c01c01C01c01c01c01; uint public constant ICO_START_TIME = 1499810400; //---------------------- Variables -------------------------// uint public current_supply = 0; // Holding the number of all the coins in existence uint public ico_starting_supply = 0; // How many atto tokens *were* available for sale at the beginning of the ICO uint public current_price_atto_tokens_per_wei = 0; // Holding current price (determined by the algorithm in buy()) //------------- Flags describing ICO stages --------------// bool public preSoldSharesDistributed = false; // Prevents accidental re-distribution of shares bool public isICOOpened = false; bool public isICOClosed = false; // 3 stages: // Contract has just been deployed and initialized. isICOOpened == false, isICOClosed == false // ICO has started, now anybody can buy(). isICOOpened == true, isICOClosed == false // ICO has finished, now the team can receive the ether. isICOOpened == false, isICOClosed == true //--------------------- Premiums -------------------------// uint[] public premiumPacks; mapping(address => uint) premiumPacksPaid; //---------------------- Events ---------------------------// event ICOOpened(); event ICOClosed(); event PriceChanged(uint old_price, uint new_price); event SupplyChanged(uint supply, uint old_supply); event RKCAcquired(address account, uint amount_in_wei, uint amount_in_rkc); // *************************************************************************** // Constructor function RKCToken() { // Some percentage of the tokens is already reserved by early employees and investors // Here we're initializing their balances distributePreSoldShares(); // Starting price current_price_atto_tokens_per_wei = calculateCurrentPrice(1); // Some other initializations premiumPacks.length = 0; } // Sending ether directly to the contract invokes buy() and assigns tokens to the sender function () payable { buy(); } // *************************************************************************** // Buy token by sending ether here // // Price is being determined by the algorithm in recalculatePrice() // You can also send the ether directly to the contract address function buy() payable { if (msg.value == 0) throw; // no tokens for you // Only works in the ICO stage, after that the token is going to be traded on the exchanges if (!isICOOpened) throw; if (isICOClosed) throw; // Deciding how many tokens can be bought with the ether received uint tokens = getAttoTokensAmountPerWeiInternal(msg.value); // Don't allow to buy more than 1% per transaction (secures from huge investors swalling the whole thing in 1 second) uint allowedInOneTransaction = current_supply / 100; if (tokens > allowedInOneTransaction) throw; // Just in case if (tokens > balances[ico_address]) throw; // Transfer from the ICO pool balances[ico_address] = balances[ico_address].sub(tokens); // if not enough, will throw balances[msg.sender] = balances[msg.sender].add(tokens); // Kick the price changing algo uint old_price = current_price_atto_tokens_per_wei; current_price_atto_tokens_per_wei = calculateCurrentPrice(getAttoTokensBoughtInICO()); if (current_price_atto_tokens_per_wei == 0) current_price_atto_tokens_per_wei = 1; // in case it is too small that it gets rounded to zero if (current_price_atto_tokens_per_wei > old_price) current_price_atto_tokens_per_wei = old_price; // in case some weird overflow happens // Broadcasting price change event if (old_price != current_price_atto_tokens_per_wei) PriceChanged(old_price, current_price_atto_tokens_per_wei); // Broadcasting the buying event RKCAcquired(msg.sender, msg.value, tokens); } // Formula for the dynamic price change algorithm function calculateCurrentPrice(uint attoTokensBought) constant returns (uint result) { // see http://www.wolframalpha.com/input/?i=f(x)+%3D+395500000+%2F+(x+%2B+150000)+-+136 return (395500000 / ((attoTokensBought / atto) + 150000)).sub(136); // mixing safe and usual math here because the division will throw on inconsistency } // *************************************************************************** // Functions for the contract owner function openICO() onlyOwner { if (isICOOpened) throw; if (isICOClosed) throw; isICOOpened = true; ICOOpened(); } function closeICO() onlyOwner { if (isICOClosed) throw; if (!isICOOpened) throw; isICOOpened = false; isICOClosed = true; // Redistribute ICO Tokens that were not bought as the first premiums premiumPacks.length = 1; premiumPacks[0] = balances[ico_address]; balances[ico_address] = 0; ICOClosed(); } function pullEtherFromContract() onlyOwner { // Only when ICO is closed if (!isICOClosed) throw; if (!teamWallet.send(this.balance)) { throw; } } // *************************************************************************** // Some percentage of the tokens is already reserved by early employees and investors // Here we're initializing their balances function distributePreSoldShares() onlyOwner { // Making it impossible to call this function twice if (preSoldSharesDistributed) throw; preSoldSharesDistributed = true; // Values are in atto tokens balances[0x7A3c869603E28b0242c129440c9dD97F8A5bEe80] = 7508811 * atto; balances[0x24a541dEAe0Fc87C990A208DE28a293fb2A982d9] = 4025712 * atto; balances[0xEcF843458e76052E6363fFb78C7535Cd87AA3AB2] = 300275 * atto; balances[0x947963ED2da750a0712AE0BF96E08C798813F277] = 150000 * atto; balances[0x82Bc8452Ab76fBA446e16b57C080F5258F557734] = 150000 * atto; balances[0x0959Ed48d55e580BB58df6E5ee01BAa787d80848] = 90000 * atto; balances[0x530A8016fB5B3d7A0F92910b4814e383835Bd51E] = 75000 * atto; balances[0xC3e934D3ADE0Ab9F61F824a9a824462c790e47B0] = 202 * atto; current_supply = (7508811 + 4025712 + 300275 + 150000 + 150000 + 90000 + 75000 + 202) * atto; // Sending the rest to ICO pool balances[ico_address] = INITIAL_SUPPLY.sub(current_supply); // Initializing the supply variables ico_starting_supply = balances[ico_address]; current_supply = INITIAL_SUPPLY; SupplyChanged(0, current_supply); } // *************************************************************************** // Some useful getters (although you can just query the public variables) function getCurrentPriceAttoTokensPerWei() constant returns (uint result) { return current_price_atto_tokens_per_wei; } function getAttoTokensAmountPerWeiInternal(uint value) payable returns (uint result) { return value * current_price_atto_tokens_per_wei; } function getAttoTokensAmountPerWei(uint value) constant returns (uint result) { return value * current_price_atto_tokens_per_wei; } function getSupply() constant returns (uint result) { return current_supply; } function getAttoTokensLeftForICO() constant returns (uint result) { return balances[ico_address]; } function getAttoTokensBoughtInICO() constant returns (uint result) { return ico_starting_supply - getAttoTokensLeftForICO(); } function getBalance(address addr) constant returns (uint balance) { return balances[addr]; } function getPremiumPack(uint index) constant returns (uint premium) { return premiumPacks[index]; } function getPremiumCount() constant returns (uint length) { return premiumPacks.length; } function getBalancePremiumsPaid(address account) constant returns (uint result) { return premiumPacksPaid[account]; } // *************************************************************************** // Premiums function sendPremiumPack(uint amount) onlyOwner allowedPayments(msg.sender, amount) { premiumPacks.length += 1; premiumPacks[premiumPacks.length-1] = amount; balances[msg.sender] = balances[msg.sender].sub(amount); // will throw and revert the whole thing if doesn't have this amount } function updatePremiums(address account) private { if (premiumPacks.length > premiumPacksPaid[account]) { uint startPackIndex = premiumPacksPaid[account]; uint finishPackIndex = premiumPacks.length - 1; for(uint i = startPackIndex; i <= finishPackIndex; i++) { if (current_supply != 0) { // just in case uint owing = balances[account] * premiumPacks[i] / current_supply; balances[account] = balances[account].add(owing); } } premiumPacksPaid[account] = premiumPacks.length; } } // *************************************************************************** // Overriding payment functions to take control over the logic modifier allowedPayments(address payer, uint value) { // Don't allow to transfer coins until the ICO ends if (isICOOpened) throw; if (!isICOClosed) throw; // Limit the quick dump possibility uint diff = 0; uint allowed = 0; if (balances[payer] > current_supply / 100) { // for balances > 1% of total supply if (block.timestamp > ICO_START_TIME) { diff = block.timestamp - ICO_START_TIME; } else { diff = ICO_START_TIME - block.timestamp; } allowed = (current_supply / 20) * (diff / (60 * 60 * 24 * 30)); // 5% unlocked every month if (value > allowed) throw; } _; } function transferFrom(address _from, address _to, uint _value) allowedPayments(_from, _value) { updatePremiums(_from); updatePremiums(_to); super.transferFrom(_from, _to, _value); } function transfer(address _to, uint _value) onlyPayloadSize(2 * 32) allowedPayments(msg.sender, _value) { updatePremiums(msg.sender); updatePremiums(_to); super.transfer(_to, _value); } }