Contract 0xf4a3679eB0A3D9e8AF9824A29BD32dD98D1E7127

 
Txn Hash
Method
Block
From
To
Value
0x654edc46e138565f008a87b7d5e5cee89f6932df3af7cb042b804af140c29a79Migrate To New N...80097022019-06-22 19:12:101201 days 19 hrs ago0x839f8516f95d5e28bca15856358ec3aa65786496 IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270 Ether0.0014822220
0xe3a8fbb03ea9c2180263b4722facba0be0adb938f5704a61c518e962c14d0f6dMigrate To New N...80087412019-06-22 15:37:071201 days 23 hrs ago0x839f8516f95d5e28bca15856358ec3aa65786496 IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270 Ether0.000083871
0x86d1fa770fe134f9328ec9128869baafbf4256dc0659b3e6b84d70f0c33b1997Approve Controll...80083042019-06-22 13:55:591202 days 1 hr ago0x839f8516f95d5e28bca15856358ec3aa65786496 IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270 Ether0.0006120220
0x89396619c1eef8168ac99311a4fb2d8a211a9bf8c9a1069da56e4c8705678a01Request Controll...80082962019-06-22 13:52:371202 days 1 hr ago0x839f8516f95d5e28bca15856358ec3aa65786496 IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270 Ether0.0009357820
0x8cb12a92b3a271b4317569fe6aee65f400d733257197f82a098840710df15479Prepare For Migr...80082382019-06-22 13:42:141202 days 1 hr ago0x839f8516f95d5e28bca15856358ec3aa65786496 IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270 Ether0.000033451.1
0xb5fb59250ced46d9fcc4faccbd7da55c719134384a0afac81097cf235f64ea8aSell73985762019-03-19 9:51:211297 days 5 hrs ago0xf28f55b702943f79e698806a005f8a45c075284b IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270 Ether0.000118781
0x6d264d42f1d05c0b01570e2bf27fbd831c8493c91fd99e6081713743adce3abfBuy73959332019-03-18 23:56:211297 days 15 hrs ago0xfd31c6acd70a0b994b1821946024538f62cbfe56 IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270.002815 Ether0.000477631
0x2a34e98a09b17e7a2f2eda1c1268e975953224d4e49e670615497e41efa4ffdcSell73943132019-03-18 17:42:531297 days 21 hrs ago0xf0da79ecbccd6ddcf5fe4a2b4e5dc11d18f75779 IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270 Ether0.001879096
0x1e811dce974efa26a17f563b82ef7a0af658bc1db4061ffea446c90e693d1b10Buy73876872019-03-17 16:54:301298 days 22 hrs ago0xf28f55b702943f79e698806a005f8a45c075284b IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270.008399 Ether0.000432561
0x9bb0a8e187b990357e0a96e2e76451e32e07a52363171ffef53f5b3c581c10e1Sell73876782019-03-17 16:53:111298 days 22 hrs ago0xf28f55b702943f79e698806a005f8a45c075284b IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270 Ether0.000118851
0x68f22dd4f7841cf6eaa40a16044af99b2c4697c7c5b0e7d245003da6aa3e3d76Sell73876632019-03-17 16:50:461298 days 22 hrs ago0xf28f55b702943f79e698806a005f8a45c075284b IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270 Ether0.000594265
0xed96bed0531c7d3f4fd6707c2f6c8125197adc7ba3af6f95263046dc6a1fc80fBuy73876022019-03-17 16:37:321298 days 22 hrs ago0xf28f55b702943f79e698806a005f8a45c075284b IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270.019754 Ether0.002171385
0x517a0161e330e90bf7f7d4b17bcd544565453d99001e9cd53221166b85bd735bBuy73867952019-03-17 13:42:441299 days 1 hr ago0xf28f55b702943f79e698806a005f8a45c075284b IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270.043645 Ether0.001303853
0xe1db1006725571312a5d676cfb30546153e54607d08a0b395c0984dd13928b83Sell73865282019-03-17 12:42:591299 days 2 hrs ago0xf28f55b702943f79e698806a005f8a45c075284b IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270 Ether0.000930223
0xe01cc667825f941df32c72a341be0521609be6a1dab17f4931c6829b4f2fcd2bSell73823862019-03-16 21:06:341299 days 18 hrs ago0xf28f55b702943f79e698806a005f8a45c075284b IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270 Ether0.000961233.1
0x7246cbda35c1f4edc83cb9ea2b1b7c0a2dd23fdab796ccb611c65d0523abb934Buy73823722019-03-16 21:02:111299 days 18 hrs ago0xf28f55b702943f79e698806a005f8a45c075284b IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270.048444 Ether0.001486983.1
0x1906c1c69353afc0a44a37457d1ab9c3628f333f9f885cbe7873c749ee9d722dBuy73658012019-03-14 7:27:401302 days 7 hrs ago0x5fbe9732a21a7dba150be930d941fde34462b52c IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270.47 Ether0.001757784
0x0d817a3d40a2f6677effc8ba43457648fa18824a0ca2e3279c8070d3b77074d7Sell73489002019-03-11 16:16:561304 days 22 hrs ago0x6a32a97a0783feea75296b155291f37fcff32599 IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270 Ether0.002185327
0xe3186aa7ecc1d12125c1d2e9355b04c4a290d31e8737bf41207cd5825edf40cfBuy73336752019-03-09 7:30:151307 days 7 hrs ago0x6a32a97a0783feea75296b155291f37fcff32599 IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71271.935943 Ether0.002342935
0xf96ecb53e43e5200ca7db3162e60e545e0bff4646d933f81ef9036e283a750baSell72608612019-02-24 8:23:331320 days 6 hrs ago0x5fbe9732a21a7dba150be930d941fde34462b52c IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270 Ether0.0031013910
0xffd66a281af87e694f8013c8b08c1f7d73f3ec094de88ead4fdbac150d5ab02aSell72525782019-02-22 9:45:571322 days 5 hrs ago0x6a32a97a0783feea75296b155291f37fcff32599 IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270 Ether0.0040455413
0x3624c2de885e0dde3d1e48e5bb0452d27f0868931c8ba65b881c29494cb8e5f7Sell72489002019-02-21 13:00:241323 days 2 hrs ago0x6a32a97a0783feea75296b155291f37fcff32599 IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270 Ether0.0046506614.9
0xbaa6a9ab9eacd1dc58c4bf41185362d7c27e49338c6234c6525cbb8e5bab4e95Sell72486812019-02-21 11:41:321323 days 3 hrs ago0x6a32a97a0783feea75296b155291f37fcff32599 IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270 Ether0.0031212510
0x0329560350bbfe1275eb5d7de2f47492caa83783771d6568f305998d1cc86b07Sell72486682019-02-21 11:35:481323 days 3 hrs ago0x6a32a97a0783feea75296b155291f37fcff32599 IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270 Ether0.0031212510
0x306bd4cae1802120a10596253b48e91965a24d0b3981617b1e2b6c1575000393Buy72424442019-02-20 0:23:561324 days 14 hrs ago0x5fbe9732a21a7dba150be930d941fde34462b52c IN  0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270.094 Ether0.0048246910
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x654edc46e138565f008a87b7d5e5cee89f6932df3af7cb042b804af140c29a7980097022019-06-22 19:12:101201 days 19 hrs ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xc1ade60ee7393c4bacd1890d1c5f4afbc3c0eca421.60795181 Ether
0xe3a8fbb03ea9c2180263b4722facba0be0adb938f5704a61c518e962c14d0f6d80087412019-06-22 15:37:071201 days 23 hrs ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xc1ade60ee7393c4bacd1890d1c5f4afbc3c0eca421.60795181 Ether
0x6d264d42f1d05c0b01570e2bf27fbd831c8493c91fd99e6081713743adce3abf73959332019-03-18 23:56:211297 days 15 hrs ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0 Ether
0x6d264d42f1d05c0b01570e2bf27fbd831c8493c91fd99e6081713743adce3abf73959332019-03-18 23:56:211297 days 15 hrs ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0 Ether
0x6d264d42f1d05c0b01570e2bf27fbd831c8493c91fd99e6081713743adce3abf73959332019-03-18 23:56:211297 days 15 hrs ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0 Ether
0x6d264d42f1d05c0b01570e2bf27fbd831c8493c91fd99e6081713743adce3abf73959332019-03-18 23:56:211297 days 15 hrs ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0 Ether
0x2a34e98a09b17e7a2f2eda1c1268e975953224d4e49e670615497e41efa4ffdc73943132019-03-18 17:42:531297 days 21 hrs ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0.00137663 Ether
0x2a34e98a09b17e7a2f2eda1c1268e975953224d4e49e670615497e41efa4ffdc73943132019-03-18 17:42:531297 days 21 hrs ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0.00137663 Ether
0x2a34e98a09b17e7a2f2eda1c1268e975953224d4e49e670615497e41efa4ffdc73943132019-03-18 17:42:531297 days 21 hrs ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0.0041299 Ether
0x2a34e98a09b17e7a2f2eda1c1268e975953224d4e49e670615497e41efa4ffdc73943132019-03-18 17:42:531297 days 21 hrs ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0.01238971 Ether
0x2a34e98a09b17e7a2f2eda1c1268e975953224d4e49e670615497e41efa4ffdc73943132019-03-18 17:42:531297 days 21 hrs ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e71270xf0da79ecbccd6ddcf5fe4a2b4e5dc11d18f757795.26664767 Ether
0x1e811dce974efa26a17f563b82ef7a0af658bc1db4061ffea446c90e693d1b1073876872019-03-17 16:54:301298 days 22 hrs ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0 Ether
0x1e811dce974efa26a17f563b82ef7a0af658bc1db4061ffea446c90e693d1b1073876872019-03-17 16:54:301298 days 22 hrs ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0 Ether
0x1e811dce974efa26a17f563b82ef7a0af658bc1db4061ffea446c90e693d1b1073876872019-03-17 16:54:301298 days 22 hrs ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0.00000001 Ether
0x1e811dce974efa26a17f563b82ef7a0af658bc1db4061ffea446c90e693d1b1073876872019-03-17 16:54:301298 days 22 hrs ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0.00000003 Ether
0xed96bed0531c7d3f4fd6707c2f6c8125197adc7ba3af6f95263046dc6a1fc80f73876022019-03-17 16:37:321298 days 22 hrs ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0.00000002 Ether
0xed96bed0531c7d3f4fd6707c2f6c8125197adc7ba3af6f95263046dc6a1fc80f73876022019-03-17 16:37:321298 days 22 hrs ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0.00000002 Ether
0xed96bed0531c7d3f4fd6707c2f6c8125197adc7ba3af6f95263046dc6a1fc80f73876022019-03-17 16:37:321298 days 22 hrs ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0.00000006 Ether
0xed96bed0531c7d3f4fd6707c2f6c8125197adc7ba3af6f95263046dc6a1fc80f73876022019-03-17 16:37:321298 days 22 hrs ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0.00000018 Ether
0x517a0161e330e90bf7f7d4b17bcd544565453d99001e9cd53221166b85bd735b73867952019-03-17 13:42:441299 days 1 hr ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0.00000009 Ether
0x517a0161e330e90bf7f7d4b17bcd544565453d99001e9cd53221166b85bd735b73867952019-03-17 13:42:441299 days 1 hr ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0.00000009 Ether
0x517a0161e330e90bf7f7d4b17bcd544565453d99001e9cd53221166b85bd735b73867952019-03-17 13:42:441299 days 1 hr ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0.00000029 Ether
0x517a0161e330e90bf7f7d4b17bcd544565453d99001e9cd53221166b85bd735b73867952019-03-17 13:42:441299 days 1 hr ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0.00000088 Ether
0xe1db1006725571312a5d676cfb30546153e54607d08a0b395c0984dd13928b8373865282019-03-17 12:42:591299 days 2 hrs ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0.00000001 Ether
0xe1db1006725571312a5d676cfb30546153e54607d08a0b395c0984dd13928b8373865282019-03-17 12:42:591299 days 2 hrs ago 0xf4a3679eb0a3d9e8af9824a29bd32dd98d1e7127 0xdffac9a5d04fb6a0f8e307551ef3f13145ac287d0.00000001 Ether
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Etherama

Compiler Version
v0.4.25+commit.59dbf8f1

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2019-01-01
*/

pragma solidity ^0.4.25;

contract IStdToken {
    function balanceOf(address _owner) public view returns (uint256);
    function transfer(address _to, uint256 _value) public returns (bool);
    function transferFrom(address _from, address _to, uint256 _value) public returns(bool);
}

contract EtheramaCommon {
    
    //main adrministrators of the Etherama network
    mapping(address => bool) private _administrators;

    //main managers of the Etherama network
    mapping(address => bool) private _managers;

    
    modifier onlyAdministrator() {
        require(_administrators[msg.sender]);
        _;
    }

    modifier onlyAdministratorOrManager() {
        require(_administrators[msg.sender] || _managers[msg.sender]);
        _;
    }
    
    constructor() public {
        _administrators[msg.sender] = true;
    }
    
    
    function addAdministator(address addr) onlyAdministrator public {
        _administrators[addr] = true;
    }

    function removeAdministator(address addr) onlyAdministrator public {
        _administrators[addr] = false;
    }

    function isAdministrator(address addr) public view returns (bool) {
        return _administrators[addr];
    }

    function addManager(address addr) onlyAdministrator public {
        _managers[addr] = true;
    }

    function removeManager(address addr) onlyAdministrator public {
        _managers[addr] = false;
    }
    
    function isManager(address addr) public view returns (bool) {
        return _managers[addr];
    }
}


contract EtheramaGasPriceLimit is EtheramaCommon {
    
    uint256 public MAX_GAS_PRICE = 0 wei;
    
    event onSetMaxGasPrice(uint256 val);    
    
    //max gas price modifier for buy/sell transactions in order to avoid a "front runner" vulnerability.
    //It is applied to all network contracts
    modifier validGasPrice(uint256 val) {
        require(val > 0);
        _;
    }
    
    constructor(uint256 maxGasPrice) public validGasPrice(maxGasPrice) {
        setMaxGasPrice(maxGasPrice);
    } 
    
    
    //only main administators or managers can set max gas price
    function setMaxGasPrice(uint256 val) public validGasPrice(val) onlyAdministratorOrManager {
        MAX_GAS_PRICE = val;
        
        emit onSetMaxGasPrice(val);
    }
}

// Core contract for Etherama network
contract EtheramaCore is EtheramaGasPriceLimit {
    
    uint256 constant public MAGNITUDE = 2**64;

    // Max and min amount of tokens which can be bought or sold. There are such limits because of math precision
    uint256 constant public MIN_TOKEN_DEAL_VAL = 0.1 ether;
    uint256 constant public MAX_TOKEN_DEAL_VAL = 1000000 ether;

    // same same for ETH
    uint256 constant public MIN_ETH_DEAL_VAL = 0.001 ether;
    uint256 constant public MAX_ETH_DEAL_VAL = 200000 ether;
    
    // percent of a transaction commission which is taken for Big Promo bonus
    uint256 public _bigPromoPercent = 5 ether;

    // percent of a transaction commission which is taken for Quick Promo bonus
    uint256 public _quickPromoPercent = 5 ether;

    // percent of a transaction commission which is taken for Etherama DEV team
    uint256 public _devRewardPercent = 15 ether;
    
    // percent of a transaction commission which is taken for Token Owner. 
    uint256 public _tokenOwnerRewardPercent = 30 ether;

    // percent of a transaction commission which is taken for share reward. Each token holder receives a small reward from each buy or sell transaction proportionally his holding. 
    uint256 public _shareRewardPercent = 25 ether;

    // percent of a transaction commission which is taken for a feraral link owner. If there is no any referal then this part of commission goes to share reward.
    uint256 public _refBonusPercent = 20 ether;

    // interval of blocks for Big Promo bonus. It means that a user which buy a bunch of tokens for X ETH in that particular block will receive a special bonus 
    uint128 public _bigPromoBlockInterval = 9999;

    // same same for Quick Promo
    uint128 public _quickPromoBlockInterval = 100;
    
    // minimum eth amount of a purchase which is required to participate in promo.
    uint256 public _promoMinPurchaseEth = 1 ether;
    
    // minimum eth purchase which is required to get a referal link.
    uint256 public _minRefEthPurchase = 0.5 ether;

    // percent of fee which is supposed to distribute.
    uint256 public _totalIncomeFeePercent = 100 ether;

    // current collected big promo bonus
    uint256 public _currentBigPromoBonus;
    // current collected quick promo bonus
    uint256 public _currentQuickPromoBonus;
    
    uint256 public _devReward;

    
    uint256 public _initBlockNum;

    mapping(address => bool) private _controllerContracts;
    mapping(uint256 => address) private _controllerIndexer;
    uint256 private _controllerContractCount;
    
    //user token balances per data contracts
    mapping(address => mapping(address => uint256)) private _userTokenLocalBalances;
    //user reward payouts per data contracts
    mapping(address => mapping(address => uint256)) private _rewardPayouts;
    //user ref rewards per data contracts
    mapping(address => mapping(address => uint256)) private _refBalances;
    //user won quick promo bonuses per data contracts
    mapping(address => mapping(address => uint256)) private _promoQuickBonuses;
    //user won big promo bonuses per data contracts
    mapping(address => mapping(address => uint256)) private _promoBigBonuses;  
    //user saldo between buys and sels in eth per data contracts
    mapping(address => mapping(address => uint256)) private _userEthVolumeSaldos;  

    //bonuses per share per data contracts
    mapping(address => uint256) private _bonusesPerShare;
    //buy counts per data contracts
    mapping(address => uint256) private _buyCounts;
    //sell counts per data contracts
    mapping(address => uint256) private _sellCounts;
    //total volume eth per data contracts
    mapping(address => uint256) private _totalVolumeEth;
    //total volume tokens per data contracts
    mapping(address => uint256) private _totalVolumeToken;

    
    event onWithdrawUserBonus(address indexed userAddress, uint256 ethWithdrawn); 


    modifier onlyController() {
        require(_controllerContracts[msg.sender]);
        _;
    }
    
    constructor(uint256 maxGasPrice) EtheramaGasPriceLimit(maxGasPrice) public { 
         _initBlockNum = block.number;
    }
    
    function getInitBlockNum() public view returns (uint256) {
        return _initBlockNum;
    }
    
    function addControllerContract(address addr) onlyAdministrator public {
        _controllerContracts[addr] = true;
        _controllerIndexer[_controllerContractCount] = addr;
        _controllerContractCount = SafeMath.add(_controllerContractCount, 1);
    }

    function removeControllerContract(address addr) onlyAdministrator public {
        _controllerContracts[addr] = false;
    }
    
    function changeControllerContract(address oldAddr, address newAddress) onlyAdministrator public {
         _controllerContracts[oldAddr] = false;
         _controllerContracts[newAddress] = true;
    }
    
    function setBigPromoInterval(uint128 val) onlyAdministrator public {
        _bigPromoBlockInterval = val;
    }

    function setQuickPromoInterval(uint128 val) onlyAdministrator public {
        _quickPromoBlockInterval = val;
    }
    
    function addBigPromoBonus() onlyController payable public {
        _currentBigPromoBonus = SafeMath.add(_currentBigPromoBonus, msg.value);
    }
    
    function addQuickPromoBonus() onlyController payable public {
        _currentQuickPromoBonus = SafeMath.add(_currentQuickPromoBonus, msg.value);
    }
    
    
    function setPromoMinPurchaseEth(uint256 val) onlyAdministrator public {
        _promoMinPurchaseEth = val;
    }
    
    function setMinRefEthPurchase(uint256 val) onlyAdministrator public {
        _minRefEthPurchase = val;
    }
    
    function setTotalIncomeFeePercent(uint256 val) onlyController public {
        require(val > 0 && val <= 100 ether);

        _totalIncomeFeePercent = val;
    }
        
    
    // set reward persentages of buy/sell fee. Token owner cannot take more than 40%.
    function setRewardPercentages(uint256 tokenOwnerRewardPercent, uint256 shareRewardPercent, uint256 refBonusPercent, uint256 bigPromoPercent, uint256 quickPromoPercent) onlyAdministrator public {
        require(tokenOwnerRewardPercent <= 40 ether);
        require(shareRewardPercent <= 100 ether);
        require(refBonusPercent <= 100 ether);
        require(bigPromoPercent <= 100 ether);
        require(quickPromoPercent <= 100 ether);

        require(tokenOwnerRewardPercent + shareRewardPercent + refBonusPercent + _devRewardPercent + _bigPromoPercent + _quickPromoPercent == 100 ether);

        _tokenOwnerRewardPercent = tokenOwnerRewardPercent;
        _shareRewardPercent = shareRewardPercent;
        _refBonusPercent = refBonusPercent;
        _bigPromoPercent = bigPromoPercent;
        _quickPromoPercent = quickPromoPercent;
    }    
    
    
    function payoutQuickBonus(address userAddress) onlyController public {
        address dataContractAddress = Etherama(msg.sender).getDataContractAddress();
        _promoQuickBonuses[dataContractAddress][userAddress] = SafeMath.add(_promoQuickBonuses[dataContractAddress][userAddress], _currentQuickPromoBonus);
        _currentQuickPromoBonus = 0;
    }
    
    function payoutBigBonus(address userAddress) onlyController public {
        address dataContractAddress = Etherama(msg.sender).getDataContractAddress();
        _promoBigBonuses[dataContractAddress][userAddress] = SafeMath.add(_promoBigBonuses[dataContractAddress][userAddress], _currentBigPromoBonus);
        _currentBigPromoBonus = 0;
    }

    function addDevReward() onlyController payable public {
        _devReward = SafeMath.add(_devReward, msg.value);
    }    
    
    function withdrawDevReward() onlyAdministrator public {
        uint256 reward = _devReward;
        _devReward = 0;

        msg.sender.transfer(reward);
    }
    
    function getBlockNumSinceInit() public view returns(uint256) {
        return block.number - getInitBlockNum();
    }

    function getQuickPromoRemainingBlocks() public view returns(uint256) {
        uint256 d = getBlockNumSinceInit() % _quickPromoBlockInterval;
        d = d == 0 ? _quickPromoBlockInterval : d;

        return _quickPromoBlockInterval - d;
    }

    function getBigPromoRemainingBlocks() public view returns(uint256) {
        uint256 d = getBlockNumSinceInit() % _bigPromoBlockInterval;
        d = d == 0 ? _bigPromoBlockInterval : d;

        return _bigPromoBlockInterval - d;
    } 
    
    
    function getBonusPerShare(address dataContractAddress) public view returns(uint256) {
        return _bonusesPerShare[dataContractAddress];
    }
    
    function getTotalBonusPerShare() public view returns (uint256 res) {
        for (uint256 i = 0; i < _controllerContractCount; i++) {
            res = SafeMath.add(res, _bonusesPerShare[Etherama(_controllerIndexer[i]).getDataContractAddress()]);
        }          
    }
    
    
    function addBonusPerShare() onlyController payable public {
        EtheramaData data = Etherama(msg.sender)._data();
        uint256 shareBonus = (msg.value * MAGNITUDE) / data.getTotalTokenSold();
        
        _bonusesPerShare[address(data)] = SafeMath.add(_bonusesPerShare[address(data)], shareBonus);
    }        
 
    function getUserRefBalance(address dataContractAddress, address userAddress) public view returns(uint256) {
        return _refBalances[dataContractAddress][userAddress];
    }
    
    function getUserRewardPayouts(address dataContractAddress, address userAddress) public view returns(uint256) {
        return _rewardPayouts[dataContractAddress][userAddress];
    }    

    function resetUserRefBalance(address userAddress) onlyController public {
        resetUserRefBalance(Etherama(msg.sender).getDataContractAddress(), userAddress);
    }
    
    function resetUserRefBalance(address dataContractAddress, address userAddress) internal {
        _refBalances[dataContractAddress][userAddress] = 0;
    }
    
    function addUserRefBalance(address userAddress) onlyController payable public {
        address dataContractAddress = Etherama(msg.sender).getDataContractAddress();
        _refBalances[dataContractAddress][userAddress] = SafeMath.add(_refBalances[dataContractAddress][userAddress], msg.value);
    }

    function addUserRewardPayouts(address userAddress, uint256 val) onlyController public {
        addUserRewardPayouts(Etherama(msg.sender).getDataContractAddress(), userAddress, val);
    }    

    function addUserRewardPayouts(address dataContractAddress, address userAddress, uint256 val) internal {
        _rewardPayouts[dataContractAddress][userAddress] = SafeMath.add(_rewardPayouts[dataContractAddress][userAddress], val);
    }

    function resetUserPromoBonus(address userAddress) onlyController public {
        resetUserPromoBonus(Etherama(msg.sender).getDataContractAddress(), userAddress);
    }
    
    function resetUserPromoBonus(address dataContractAddress, address userAddress) internal {
        _promoQuickBonuses[dataContractAddress][userAddress] = 0;
        _promoBigBonuses[dataContractAddress][userAddress] = 0;
    }
    
    
    function trackBuy(address userAddress, uint256 volEth, uint256 volToken) onlyController public {
        address dataContractAddress = Etherama(msg.sender).getDataContractAddress();
        _buyCounts[dataContractAddress] = SafeMath.add(_buyCounts[dataContractAddress], 1);
        _userEthVolumeSaldos[dataContractAddress][userAddress] = SafeMath.add(_userEthVolumeSaldos[dataContractAddress][userAddress], volEth);
        
        trackTotalVolume(dataContractAddress, volEth, volToken);
    }

    function trackSell(address userAddress, uint256 volEth, uint256 volToken) onlyController public {
        address dataContractAddress = Etherama(msg.sender).getDataContractAddress();
        _sellCounts[dataContractAddress] = SafeMath.add(_sellCounts[dataContractAddress], 1);
        _userEthVolumeSaldos[dataContractAddress][userAddress] = SafeMath.sub(_userEthVolumeSaldos[dataContractAddress][userAddress], volEth);
        
        trackTotalVolume(dataContractAddress, volEth, volToken);
    }
    
    function trackTotalVolume(address dataContractAddress, uint256 volEth, uint256 volToken) internal {
        _totalVolumeEth[dataContractAddress] = SafeMath.add(_totalVolumeEth[dataContractAddress], volEth);
        _totalVolumeToken[dataContractAddress] = SafeMath.add(_totalVolumeToken[dataContractAddress], volToken);
    }
    
    function getBuyCount(address dataContractAddress) public view returns (uint256) {
        return _buyCounts[dataContractAddress];
    }
    
    function getTotalBuyCount() public view returns (uint256 res) {
        for (uint256 i = 0; i < _controllerContractCount; i++) {
            res = SafeMath.add(res, _buyCounts[Etherama(_controllerIndexer[i]).getDataContractAddress()]);
        }         
    }
    
    function getSellCount(address dataContractAddress) public view returns (uint256) {
        return _sellCounts[dataContractAddress];
    }
    
    function getTotalSellCount() public view returns (uint256 res) {
        for (uint256 i = 0; i < _controllerContractCount; i++) {
            res = SafeMath.add(res, _sellCounts[Etherama(_controllerIndexer[i]).getDataContractAddress()]);
        }         
    }

    function getTotalVolumeEth(address dataContractAddress) public view returns (uint256) {
        return _totalVolumeEth[dataContractAddress];
    }
    
    function getTotalVolumeToken(address dataContractAddress) public view returns (uint256) {
        return _totalVolumeToken[dataContractAddress];
    }

    function getUserEthVolumeSaldo(address dataContractAddress, address userAddress) public view returns (uint256) {
        return _userEthVolumeSaldos[dataContractAddress][userAddress];
    }
    
    function getUserTotalEthVolumeSaldo(address userAddress) public view returns (uint256 res) {
        for (uint256 i = 0; i < _controllerContractCount; i++) {
            res = SafeMath.add(res, _userEthVolumeSaldos[Etherama(_controllerIndexer[i]).getDataContractAddress()][userAddress]);
        } 
    }
    
    function getTotalCollectedPromoBonus() public view returns (uint256) {
        return SafeMath.add(_currentBigPromoBonus, _currentQuickPromoBonus);
    }

    function getUserTotalPromoBonus(address dataContractAddress, address userAddress) public view returns (uint256) {
        return SafeMath.add(_promoQuickBonuses[dataContractAddress][userAddress], _promoBigBonuses[dataContractAddress][userAddress]);
    }
    
    function getUserQuickPromoBonus(address dataContractAddress, address userAddress) public view returns (uint256) {
        return _promoQuickBonuses[dataContractAddress][userAddress];
    }
    
    function getUserBigPromoBonus(address dataContractAddress, address userAddress) public view returns (uint256) {
        return _promoBigBonuses[dataContractAddress][userAddress];
    }

    
    function getUserTokenLocalBalance(address dataContractAddress, address userAddress) public view returns(uint256) {
        return _userTokenLocalBalances[dataContractAddress][userAddress];
    }
  
    
    function addUserTokenLocalBalance(address userAddress, uint256 val) onlyController public {
        address dataContractAddress = Etherama(msg.sender).getDataContractAddress();
        _userTokenLocalBalances[dataContractAddress][userAddress] = SafeMath.add(_userTokenLocalBalances[dataContractAddress][userAddress], val);
    }
    
    function subUserTokenLocalBalance(address userAddress, uint256 val) onlyController public {
        address dataContractAddress = Etherama(msg.sender).getDataContractAddress();
        _userTokenLocalBalances[dataContractAddress][userAddress] = SafeMath.sub(_userTokenLocalBalances[dataContractAddress][userAddress], val);
    }

  
    function getUserReward(address dataContractAddress, address userAddress, bool incShareBonus, bool incRefBonus, bool incPromoBonus) public view returns(uint256 reward) {
        EtheramaData data = EtheramaData(dataContractAddress);
        
        if (incShareBonus) {
            reward = data.getBonusPerShare() * data.getActualUserTokenBalance(userAddress);
            reward = ((reward < data.getUserRewardPayouts(userAddress)) ? 0 : SafeMath.sub(reward, data.getUserRewardPayouts(userAddress))) / MAGNITUDE;
        }
        
        if (incRefBonus) reward = SafeMath.add(reward, data.getUserRefBalance(userAddress));
        if (incPromoBonus) reward = SafeMath.add(reward, data.getUserTotalPromoBonus(userAddress));
        
        return reward;
    }
    
    //user's total reward from all the tokens on the table. includes share reward + referal bonus + promo bonus
    function getUserTotalReward(address userAddress, bool incShareBonus, bool incRefBonus, bool incPromoBonus) public view returns(uint256 res) {
        for (uint256 i = 0; i < _controllerContractCount; i++) {
            address dataContractAddress = Etherama(_controllerIndexer[i]).getDataContractAddress();
            
            res = SafeMath.add(res, getUserReward(dataContractAddress, userAddress, incShareBonus, incRefBonus, incPromoBonus));
        }
    }
    
    //current user's reward
    function getCurrentUserReward(bool incRefBonus, bool incPromoBonus) public view returns(uint256) {
        return getUserTotalReward(msg.sender, true, incRefBonus, incPromoBonus);
    }
 
    //current user's total reward from all the tokens on the table
    function getCurrentUserTotalReward() public view returns(uint256) {
        return getUserTotalReward(msg.sender, true, true, true);
    }
    
    //user's share bonus from all the tokens on the table
    function getCurrentUserShareBonus() public view returns(uint256) {
        return getUserTotalReward(msg.sender, true, false, false);
    }
    
    //current user's ref bonus from all the tokens on the table
    function getCurrentUserRefBonus() public view returns(uint256) {
        return getUserTotalReward(msg.sender, false, true, false);
    }
    
    //current user's promo bonus from all the tokens on the table
    function getCurrentUserPromoBonus() public view returns(uint256) {
        return getUserTotalReward(msg.sender, false, false, true);
    }
    
    //is ref link available for the user
    function isRefAvailable(address refAddress) public view returns(bool) {
        return getUserTotalEthVolumeSaldo(refAddress) >= _minRefEthPurchase;
    }
    
    //is ref link available for the current user
    function isRefAvailable() public view returns(bool) {
        return isRefAvailable(msg.sender);
    }
    
     //Withdraws all of the user earnings.
    function withdrawUserReward() public {
        uint256 reward = getRewardAndPrepareWithdraw();
        
        require(reward > 0);
        
        msg.sender.transfer(reward);
        
        emit onWithdrawUserBonus(msg.sender, reward);
    }

    //gather all the user's reward and prepare it to withdaw
    function getRewardAndPrepareWithdraw() internal returns(uint256 reward) {
        
        for (uint256 i = 0; i < _controllerContractCount; i++) {

            address dataContractAddress = Etherama(_controllerIndexer[i]).getDataContractAddress();
            
            reward = SafeMath.add(reward, getUserReward(dataContractAddress, msg.sender, true, false, false));

            // add share reward to payouts
            addUserRewardPayouts(dataContractAddress, msg.sender, reward * MAGNITUDE);

            // add ref bonus
            reward = SafeMath.add(reward, getUserRefBalance(dataContractAddress, msg.sender));
            resetUserRefBalance(dataContractAddress, msg.sender);
            
            // add promo bonus
            reward = SafeMath.add(reward, getUserTotalPromoBonus(dataContractAddress, msg.sender));
            resetUserPromoBonus(dataContractAddress, msg.sender);
        }
        
        return reward;
    }
    
    //withdaw all the remamining ETH if there is no one active contract. We don't want to leave them here forever
    function withdrawRemainingEthAfterAll() onlyAdministrator public {
        for (uint256 i = 0; i < _controllerContractCount; i++) {
            if (Etherama(_controllerIndexer[i]).isActive()) revert();
        }
        
        msg.sender.transfer(address(this).balance);
    }

    
    
    function calcPercent(uint256 amount, uint256 percent) public pure returns(uint256) {
        return SafeMath.div(SafeMath.mul(SafeMath.div(amount, 100), percent), 1 ether);
    }

    //Converts real num to uint256. Works only with positive numbers.
    function convertRealTo256(int128 realVal) public pure returns(uint256) {
        int128 roundedVal = RealMath.fromReal(RealMath.mul(realVal, RealMath.toReal(1e12)));

        return SafeMath.mul(uint256(roundedVal), uint256(1e6));
    }

    //Converts uint256 to real num. Possible a little loose of precision
    function convert256ToReal(uint256 val) public pure returns(int128) {
        uint256 intVal = SafeMath.div(val, 1e6);
        require(RealMath.isUInt256ValidIn64(intVal));
        
        return RealMath.fraction(int64(intVal), 1e12);
    }    
}

// Data contract for Etherama contract controller. Data contract cannot be changed so no data can be lost. On the other hand Etherama controller can be replaced if some error is found.
contract EtheramaData {

    // tranding token address
    address constant public TOKEN_CONTRACT_ADDRESS = 0x83cee9e086A77e492eE0bB93C2B0437aD6fdECCc;
    
    // token price in the begining
    uint256 constant public TOKEN_PRICE_INITIAL = 0.0023 ether;
    // a percent of the token price which adds/subs each _priceSpeedInterval tokens
    uint64 constant public PRICE_SPEED_PERCENT = 5;
    // Token price speed interval. For instance, if PRICE_SPEED_PERCENT = 5 and PRICE_SPEED_INTERVAL = 10000 it means that after 10000 tokens are bought/sold  token price will increase/decrease for 5%.
    uint64 constant public PRICE_SPEED_INTERVAL = 10000;
    // lock-up period in days. Until this period is expeired nobody can close the contract or withdraw users' funds
    uint64 constant public EXP_PERIOD_DAYS = 365;

    
    mapping(address => bool) private _administrators;
    uint256 private  _administratorCount;

    uint64 public _initTime;
    uint64 public _expirationTime;
    uint256 public _tokenOwnerReward;
    
    uint256 public _totalSupply;
    int128 public _realTokenPrice;

    address public _controllerAddress = address(0x0);

    EtheramaCore public _core;

    uint256 public _initBlockNum;
    
    bool public _hasMaxPurchaseLimit = false;
    
    IStdToken public _token;

    //only main contract
    modifier onlyController() {
        require(msg.sender == _controllerAddress);
        _;
    }

    constructor(address coreAddress) public {
        require(coreAddress != address(0x0));

        _core = EtheramaCore(coreAddress);
        _initBlockNum = block.number;
    }
    
    function init() public {
        require(_controllerAddress == address(0x0));
        require(TOKEN_CONTRACT_ADDRESS != address(0x0));
        require(RealMath.isUInt64ValidIn64(PRICE_SPEED_PERCENT) && PRICE_SPEED_PERCENT > 0);
        require(RealMath.isUInt64ValidIn64(PRICE_SPEED_INTERVAL) && PRICE_SPEED_INTERVAL > 0);
        
        
        _controllerAddress = msg.sender;

        _token = IStdToken(TOKEN_CONTRACT_ADDRESS);
        _initTime = uint64(now);
        _expirationTime = _initTime + EXP_PERIOD_DAYS * 1 days;
        _realTokenPrice = _core.convert256ToReal(TOKEN_PRICE_INITIAL);
    }
    
    function isInited()  public view returns(bool) {
        return (_controllerAddress != address(0x0));
    }
    
    function getCoreAddress()  public view returns(address) {
        return address(_core);
    }
    

    function setNewControllerAddress(address newAddress) onlyController public {
        _controllerAddress = newAddress;
    }


    
    function getPromoMinPurchaseEth() public view returns(uint256) {
        return _core._promoMinPurchaseEth();
    }

    function addAdministator(address addr) onlyController public {
        _administrators[addr] = true;
        _administratorCount = SafeMath.add(_administratorCount, 1);
    }

    function removeAdministator(address addr) onlyController public {
        _administrators[addr] = false;
        _administratorCount = SafeMath.sub(_administratorCount, 1);
    }

    function getAdministratorCount() public view returns(uint256) {
        return _administratorCount;
    }
    
    function isAdministrator(address addr) public view returns(bool) {
        return _administrators[addr];
    }

    
    function getCommonInitBlockNum() public view returns (uint256) {
        return _core.getInitBlockNum();
    }
    
    
    function resetTokenOwnerReward() onlyController public {
        _tokenOwnerReward = 0;
    }
    
    function addTokenOwnerReward(uint256 val) onlyController public {
        _tokenOwnerReward = SafeMath.add(_tokenOwnerReward, val);
    }
    
    function getCurrentBigPromoBonus() public view returns (uint256) {
        return _core._currentBigPromoBonus();
    }        
    

    function getCurrentQuickPromoBonus() public view returns (uint256) {
        return _core._currentQuickPromoBonus();
    }    

    function getTotalCollectedPromoBonus() public view returns (uint256) {
        return _core.getTotalCollectedPromoBonus();
    }    

    function setTotalSupply(uint256 val) onlyController public {
        _totalSupply = val;
    }
    
    function setRealTokenPrice(int128 val) onlyController public {
        _realTokenPrice = val;
    }    
    
    
    function setHasMaxPurchaseLimit(bool val) onlyController public {
        _hasMaxPurchaseLimit = val;
    }
    
    function getUserTokenLocalBalance(address userAddress) public view returns(uint256) {
        return _core.getUserTokenLocalBalance(address(this), userAddress);
    }
    
    function getActualUserTokenBalance(address userAddress) public view returns(uint256) {
        return SafeMath.min(getUserTokenLocalBalance(userAddress), _token.balanceOf(userAddress));
    }  
    
    function getBonusPerShare() public view returns(uint256) {
        return _core.getBonusPerShare(address(this));
    }
    
    function getUserRewardPayouts(address userAddress) public view returns(uint256) {
        return _core.getUserRewardPayouts(address(this), userAddress);
    }
    
    function getUserRefBalance(address userAddress) public view returns(uint256) {
        return _core.getUserRefBalance(address(this), userAddress);
    }
    
    function getUserReward(address userAddress, bool incRefBonus, bool incPromoBonus) public view returns(uint256) {
        return _core.getUserReward(address(this), userAddress, true, incRefBonus, incPromoBonus);
    }
    
    function getUserTotalPromoBonus(address userAddress) public view returns(uint256) {
        return _core.getUserTotalPromoBonus(address(this), userAddress);
    }
    
    function getUserBigPromoBonus(address userAddress) public view returns(uint256) {
        return _core.getUserBigPromoBonus(address(this), userAddress);
    }

    function getUserQuickPromoBonus(address userAddress) public view returns(uint256) {
        return _core.getUserQuickPromoBonus(address(this), userAddress);
    }

    function getRemainingTokenAmount() public view returns(uint256) {
        return _token.balanceOf(_controllerAddress);
    }

    function getTotalTokenSold() public view returns(uint256) {
        return _totalSupply - getRemainingTokenAmount();
    }   
    
    function getUserEthVolumeSaldo(address userAddress) public view returns(uint256) {
        return _core.getUserEthVolumeSaldo(address(this), userAddress);
    }

}


contract Etherama {

    IStdToken public _token;
    EtheramaData public _data;
    EtheramaCore public _core;


    bool public isActive = false;
    bool public isMigrationToNewControllerInProgress = false;
    bool public isActualContractVer = true;
    address public migrationContractAddress = address(0x0);
    bool public isMigrationApproved = false;

    address private _creator = address(0x0);
    

    event onTokenPurchase(address indexed userAddress, uint256 incomingEth, uint256 tokensMinted, address indexed referredBy);
    
    event onTokenSell(address indexed userAddress, uint256 tokensBurned, uint256 ethEarned);
    
    event onReinvestment(address indexed userAddress, uint256 ethReinvested, uint256 tokensMinted);
    
    event onWithdrawTokenOwnerReward(address indexed toAddress, uint256 ethWithdrawn); 

    event onWinQuickPromo(address indexed userAddress, uint256 ethWon);    
   
    event onWinBigPromo(address indexed userAddress, uint256 ethWon);    


    // only people with tokens
    modifier onlyContractUsers() {
        require(getUserLocalTokenBalance(msg.sender) > 0);
        _;
    }
    

    // administrators can:
    // -> change minimal amout of tokens to get a ref link.
    // administrators CANNOT:
    // -> take funds
    // -> disable withdrawals
    // -> kill the contract
    // -> change the price of tokens
    // -> suspend the contract
    modifier onlyAdministrator() {
        require(isCurrentUserAdministrator());
        _;
    }
    
    //core administrator can only approve contract migration after its code review
    modifier onlyCoreAdministrator() {
        require(_core.isAdministrator(msg.sender));
        _;
    }

    // only active state of the contract. Administator can activate it, but canncon deactive untill lock-up period is expired.
    modifier onlyActive() {
        require(isActive);
        _;
    }

    // maximum gas price for buy/sell transactions to avoid "front runner" vulnerability.   
    modifier validGasPrice() {
        require(tx.gasprice <= _core.MAX_GAS_PRICE());
        _;
    }
    
    // eth value must be greater than 0 for purchase transactions
    modifier validPayableValue() {
        require(msg.value > 0);
        _;
    }
    
    modifier onlyCoreContract() {
        require(msg.sender == _data.getCoreAddress());
        _;
    }

    // dataContractAddress - data contract address where all the data is collected and separated from the controller
    constructor(address dataContractAddress) public {
        
        require(dataContractAddress != address(0x0));
        _data = EtheramaData(dataContractAddress);
        
        if (!_data.isInited()) {
            _data.init();
            _data.addAdministator(msg.sender);
            _creator = msg.sender;
        }
        
        _token = _data._token();
        _core = _data._core();
    }



    function addAdministator(address addr) onlyAdministrator public {
        _data.addAdministator(addr);
    }

    function removeAdministator(address addr) onlyAdministrator public {
        _data.removeAdministator(addr);
    }

    // transfer ownership request of the contract to token owner from contract creator. The new administator has to accept ownership to finish the transferring.
    function transferOwnershipRequest(address addr) onlyAdministrator public {
        addAdministator(addr);
    }

    // accept transfer ownership.
    function acceptOwnership() onlyAdministrator public {
        require(_creator != address(0x0));

        removeAdministator(_creator);

        require(_data.getAdministratorCount() == 1);
    }
    
    // if there is a maximim purchase limit then a user can buy only amount of tokens which he had before, not more.
    function setHasMaxPurchaseLimit(bool val) onlyAdministrator public {
        _data.setHasMaxPurchaseLimit(val);
    }
        
    // activate the controller contract. After calling this function anybody can start trading the contrant's tokens
    function activate() onlyAdministrator public {
        require(!isActive);
        
        if (getTotalTokenSupply() == 0) setTotalSupply();
        require(getTotalTokenSupply() > 0);
        
        isActive = true;
        isMigrationToNewControllerInProgress = false;
    }

    // Close the contract and withdraw all the funds. The contract cannot be closed before lock up period is expired.
    function finish() onlyActive onlyAdministrator public {
        require(uint64(now) >= _data._expirationTime());
        
        _token.transfer(msg.sender, getRemainingTokenAmount());   
        msg.sender.transfer(getTotalEthBalance());
        
        isActive = false;
    }
    
    //Converts incoming eth to tokens
    function buy(address refAddress, uint256 minReturn) onlyActive validGasPrice validPayableValue public payable returns(uint256) {
        return purchaseTokens(msg.value, refAddress, minReturn);
    }

    //sell tokens for eth. before call this func you have to call "approve" in the ERC20 token contract
    function sell(uint256 tokenAmount, uint256 minReturn) onlyActive onlyContractUsers validGasPrice public returns(uint256) {
        if (tokenAmount > getCurrentUserLocalTokenBalance() || tokenAmount == 0) return 0;

        uint256 ethAmount = 0; uint256 totalFeeEth = 0; uint256 tokenPrice = 0;
        (ethAmount, totalFeeEth, tokenPrice) = estimateSellOrder(tokenAmount, true);
        require(ethAmount >= minReturn);

        subUserTokens(msg.sender, tokenAmount);

        msg.sender.transfer(ethAmount);

        updateTokenPrice(-_core.convert256ToReal(tokenAmount));

        distributeFee(totalFeeEth, address(0x0));
        
        uint256 userEthVol = _data.getUserEthVolumeSaldo(msg.sender);
        _core.trackSell(msg.sender, ethAmount > userEthVol ? userEthVol : ethAmount, tokenAmount);
       
        emit onTokenSell(msg.sender, tokenAmount, ethAmount);

        return ethAmount;
    }   

    function transferTokens(address toUser, uint256 tokenAmount) onlyActive onlyContractUsers public {
        require(getUserLocalTokenBalance(msg.sender) >= tokenAmount);
        
        _core.subUserTokenLocalBalance(msg.sender, tokenAmount);
        _core.addUserTokenLocalBalance(toUser, tokenAmount);
        _token.transferFrom(msg.sender, toUser, tokenAmount);
    }

    //Fallback function to handle eth that was sent straight to the contract
    function() onlyActive validGasPrice validPayableValue payable external {
        purchaseTokens(msg.value, address(0x0), 1);
    }

    // withdraw token owner's reward
    function withdrawTokenOwnerReward() onlyAdministrator public {
        uint256 reward = getTokenOwnerReward();
        
        require(reward > 0);
        
        _data.resetTokenOwnerReward();

        msg.sender.transfer(reward);

        emit onWithdrawTokenOwnerReward(msg.sender, reward);
    }

    // prepare the contract for migration to another one in case of some errors or refining
    function prepareForMigration() onlyAdministrator public {
        require(!isMigrationToNewControllerInProgress);
        isMigrationToNewControllerInProgress = true;
    }

    // accept funds transfer to a new controller during a migration.
    function migrateFunds() payable public {
        require(isMigrationToNewControllerInProgress);
    }
    

    //HELPERS

    // max gas price for buy/sell transactions  
    function getMaxGasPrice() public view returns(uint256) {
        return _core.MAX_GAS_PRICE();
    }

    // max gas price for buy/sell transactions
    function getExpirationTime() public view returns (uint256) {
        return _data._expirationTime();
    }
            
    // time till lock-up period is expired 
    function getRemainingTimeTillExpiration() public view returns (uint256) {
        if (_data._expirationTime() <= uint64(now)) return 0;
        
        return _data._expirationTime() - uint64(now);
    }

    
    function isCurrentUserAdministrator() public view returns(bool) {
        return _data.isAdministrator(msg.sender);
    }

    //data contract address where all the data is holded
    function getDataContractAddress() public view returns(address) {
        return address(_data);
    }

    // get trading token contract address
    function getTokenAddress() public view returns(address) {
        return address(_token);
    }

    // request migration to new contract. After request Etherama dev team should review its code and approve it if it is OK
    function requestControllerContractMigration(address newControllerAddr) onlyAdministrator public {
        require(!isMigrationApproved);
        
        migrationContractAddress = newControllerAddr;
    }
    
    // Dev team gives a pervission to updagrade the contract after code review, transfer all the funds, activate new abilities or fix some errors.
    function approveControllerContractMigration() onlyCoreAdministrator public {
        isMigrationApproved = true;
    }
    
    //migrate to new controller contract in case of some mistake in the contract and transfer there all the tokens and eth. It can be done only after code review by Etherama developers.
    function migrateToNewNewControllerContract() onlyAdministrator public {
        require(isMigrationApproved && migrationContractAddress != address(0x0) && isActualContractVer);
        
        isActive = false;

        Etherama newController = Etherama(address(migrationContractAddress));
        _data.setNewControllerAddress(migrationContractAddress);

        uint256 remainingTokenAmount = getRemainingTokenAmount();
        uint256 ethBalance = getTotalEthBalance();

        if (remainingTokenAmount > 0) _token.transfer(migrationContractAddress, remainingTokenAmount); 
        if (ethBalance > 0) newController.migrateFunds.value(ethBalance)();
        
        isActualContractVer = false;
    }

    //total buy count
    function getBuyCount() public view returns(uint256) {
        return _core.getBuyCount(getDataContractAddress());
    }
    //total sell count
    function getSellCount() public view returns(uint256) {
        return _core.getSellCount(getDataContractAddress());
    }
    //total eth volume
    function getTotalVolumeEth() public view returns(uint256) {
        return _core.getTotalVolumeEth(getDataContractAddress());
    }   
    //total token volume
    function getTotalVolumeToken() public view returns(uint256) {
        return _core.getTotalVolumeToken(getDataContractAddress());
    } 
    //current bonus per 1 token in ETH
    function getBonusPerShare() public view returns (uint256) {
        return SafeMath.div(SafeMath.mul(_data.getBonusPerShare(), 1 ether), _core.MAGNITUDE());
    }    
    //token initial price in ETH
    function getTokenInitialPrice() public view returns(uint256) {
        return _data.TOKEN_PRICE_INITIAL();
    }

    function getDevRewardPercent() public view returns(uint256) {
        return _core._devRewardPercent();
    }

    function getTokenOwnerRewardPercent() public view returns(uint256) {
        return _core._tokenOwnerRewardPercent();
    }
    
    function getShareRewardPercent() public view returns(uint256) {
        return _core._shareRewardPercent();
    }
    
    function getRefBonusPercent() public view returns(uint256) {
        return _core._refBonusPercent();
    }
    
    function getBigPromoPercent() public view returns(uint256) {
        return _core._bigPromoPercent();
    }
    
    function getQuickPromoPercent() public view returns(uint256) {
        return _core._quickPromoPercent();
    }

    function getBigPromoBlockInterval() public view returns(uint256) {
        return _core._bigPromoBlockInterval();
    }

    function getQuickPromoBlockInterval() public view returns(uint256) {
        return _core._quickPromoBlockInterval();
    }

    function getPromoMinPurchaseEth() public view returns(uint256) {
        return _core._promoMinPurchaseEth();
    }


    function getPriceSpeedPercent() public view returns(uint64) {
        return _data.PRICE_SPEED_PERCENT();
    }

    function getPriceSpeedTokenBlock() public view returns(uint64) {
        return _data.PRICE_SPEED_INTERVAL();
    }

    function getMinRefEthPurchase() public view returns (uint256) {
        return _core._minRefEthPurchase();
    }    

    function getTotalCollectedPromoBonus() public view returns (uint256) {
        return _data.getTotalCollectedPromoBonus();
    }   

    function getCurrentBigPromoBonus() public view returns (uint256) {
        return _data.getCurrentBigPromoBonus();
    }  

    function getCurrentQuickPromoBonus() public view returns (uint256) {
        return _data.getCurrentQuickPromoBonus();
    }    

    //current token price
    function getCurrentTokenPrice() public view returns(uint256) {
        return _core.convertRealTo256(_data._realTokenPrice());
    }

    //contract's eth balance
    function getTotalEthBalance() public view returns(uint256) {
        return address(this).balance;
    }
    
    //amount of tokens which were funded to the contract initially
    function getTotalTokenSupply() public view returns(uint256) {
        return _data._totalSupply();
    }

    //amount of tokens which are still available for selling on the contract
    function getRemainingTokenAmount() public view returns(uint256) {
        return _token.balanceOf(address(this));
    }
    
    //amount of tokens which where sold by the contract
    function getTotalTokenSold() public view returns(uint256) {
        return getTotalTokenSupply() - getRemainingTokenAmount();
    }
    
    //user's token amount which were bought from the contract
    function getUserLocalTokenBalance(address userAddress) public view returns(uint256) {
        return _data.getUserTokenLocalBalance(userAddress);
    }
    
    //current user's token amount which were bought from the contract
    function getCurrentUserLocalTokenBalance() public view returns(uint256) {
        return getUserLocalTokenBalance(msg.sender);
    }    

    //is referal link available for the current user
    function isCurrentUserRefAvailable() public view returns(bool) {
        return _core.isRefAvailable();
    }


    function getCurrentUserRefBonus() public view returns(uint256) {
        return _data.getUserRefBalance(msg.sender);
    }
    
    function getCurrentUserPromoBonus() public view returns(uint256) {
        return _data.getUserTotalPromoBonus(msg.sender);
    }
    
    //max and min values of a deal in tokens
    function getTokenDealRange() public view returns(uint256, uint256) {
        return (_core.MIN_TOKEN_DEAL_VAL(), _core.MAX_TOKEN_DEAL_VAL());
    }
    
    //max and min values of a deal in ETH
    function getEthDealRange() public view returns(uint256, uint256) {
        uint256 minTokenVal; uint256 maxTokenVal;
        (minTokenVal, maxTokenVal) = getTokenDealRange();
        
        return ( SafeMath.max(_core.MIN_ETH_DEAL_VAL(), tokensToEth(minTokenVal, true)), SafeMath.min(_core.MAX_ETH_DEAL_VAL(), tokensToEth(maxTokenVal, true)) );
    }
    
    //user's total reward from all the tokens on the table. includes share reward + referal bonus + promo bonus
    function getUserReward(address userAddress, bool isTotal) public view returns(uint256) {
        return isTotal ? 
            _core.getUserTotalReward(userAddress, true, true, true) :
            _data.getUserReward(userAddress, true, true);
    }
    
    //price for selling 1 token. mostly useful only for frontend
    function get1TokenSellPrice() public view returns(uint256) {
        uint256 tokenAmount = 1 ether;

        uint256 ethAmount = 0; uint256 totalFeeEth = 0; uint256 tokenPrice = 0;
        (ethAmount, totalFeeEth, tokenPrice) = estimateSellOrder(tokenAmount, true);

        return ethAmount;
    }
    
    //price for buying 1 token. mostly useful only for frontend
    function get1TokenBuyPrice() public view returns(uint256) {
        uint256 ethAmount = 1 ether;

        uint256 tokenAmount = 0; uint256 totalFeeEth = 0; uint256 tokenPrice = 0;
        (tokenAmount, totalFeeEth, tokenPrice) = estimateBuyOrder(ethAmount, true);  

        return SafeMath.div(ethAmount * 1 ether, tokenAmount);
    }

    //calc current reward for holding @tokenAmount tokens
    function calcReward(uint256 tokenAmount) public view returns(uint256) {
        return (uint256) ((int256)(_data.getBonusPerShare() * tokenAmount)) / _core.MAGNITUDE();
    }  

    //esimate buy order by amount of ETH/tokens. returns tokens/eth amount after the deal, total fee in ETH and average token price
    function estimateBuyOrder(uint256 amount, bool fromEth) public view returns(uint256, uint256, uint256) {
        uint256 minAmount; uint256 maxAmount;
        (minAmount, maxAmount) = fromEth ? getEthDealRange() : getTokenDealRange();
        //require(amount >= minAmount && amount <= maxAmount);

        uint256 ethAmount = fromEth ? amount : tokensToEth(amount, true);
        require(ethAmount > 0);

        uint256 tokenAmount = fromEth ? ethToTokens(amount, true) : amount;
        uint256 totalFeeEth = calcTotalFee(tokenAmount, true);
        require(ethAmount > totalFeeEth);

        uint256 tokenPrice = SafeMath.div(ethAmount * 1 ether, tokenAmount);

        return (fromEth ? tokenAmount : SafeMath.add(ethAmount, totalFeeEth), totalFeeEth, tokenPrice);
    }
    
    //esimate sell order by amount of tokens/ETH. returns eth/tokens amount after the deal, total fee in ETH and average token price
    function estimateSellOrder(uint256 amount, bool fromToken) public view returns(uint256, uint256, uint256) {
        uint256 minAmount; uint256 maxAmount;
        (minAmount, maxAmount) = fromToken ? getTokenDealRange() : getEthDealRange();
        //require(amount >= minAmount && amount <= maxAmount);

        uint256 tokenAmount = fromToken ? amount : ethToTokens(amount, false);
        require(tokenAmount > 0);
        
        uint256 ethAmount = fromToken ? tokensToEth(tokenAmount, false) : amount;
        uint256 totalFeeEth = calcTotalFee(tokenAmount, false);
        require(ethAmount > totalFeeEth);

        uint256 tokenPrice = SafeMath.div(ethAmount * 1 ether, tokenAmount);
        
        return (fromToken ? ethAmount : tokenAmount, totalFeeEth, tokenPrice);
    }

    //returns max user's purchase limit in tokens if _hasMaxPurchaseLimit pamam is set true. If it is a user cannot by more tokens that hs already bought on some other exchange
    function getUserMaxPurchase(address userAddress) public view returns(uint256) {
        return _token.balanceOf(userAddress) - SafeMath.mul(getUserLocalTokenBalance(userAddress), 2);
    }
    //current urser's max purchase limit in tokens
    function getCurrentUserMaxPurchase() public view returns(uint256) {
        return getUserMaxPurchase(msg.sender);
    }

    //token owener collected reward
    function getTokenOwnerReward() public view returns(uint256) {
        return _data._tokenOwnerReward();
    }

    //current user's won promo bonuses
    function getCurrentUserTotalPromoBonus() public view returns(uint256) {
        return _data.getUserTotalPromoBonus(msg.sender);
    }

    //current user's won big promo bonuses
    function getCurrentUserBigPromoBonus() public view returns(uint256) {
        return _data.getUserBigPromoBonus(msg.sender);
    }
    //current user's won quick promo bonuses
    function getCurrentUserQuickPromoBonus() public view returns(uint256) {
        return _data.getUserQuickPromoBonus(msg.sender);
    }
   
    //amount of block since core contract is deployed
    function getBlockNumSinceInit() public view returns(uint256) {
        return _core.getBlockNumSinceInit();
    }

    //remaing amount of blocks to win a quick promo bonus
    function getQuickPromoRemainingBlocks() public view returns(uint256) {
        return _core.getQuickPromoRemainingBlocks();
    }
    //remaing amount of blocks to win a big promo bonus
    function getBigPromoRemainingBlocks() public view returns(uint256) {
        return _core.getBigPromoRemainingBlocks();
    } 
    
    
    // INTERNAL FUNCTIONS
    
    function purchaseTokens(uint256 ethAmount, address refAddress, uint256 minReturn) internal returns(uint256) {
        uint256 tokenAmount = 0; uint256 totalFeeEth = 0; uint256 tokenPrice = 0;
        (tokenAmount, totalFeeEth, tokenPrice) = estimateBuyOrder(ethAmount, true);
        require(tokenAmount >= minReturn);

        if (_data._hasMaxPurchaseLimit()) {
            //user has to have at least equal amount of tokens which he's willing to buy 
            require(getCurrentUserMaxPurchase() >= tokenAmount);
        }

        require(tokenAmount > 0 && (SafeMath.add(tokenAmount, getTotalTokenSold()) > getTotalTokenSold()));

        if (refAddress == msg.sender || !_core.isRefAvailable(refAddress)) refAddress = address(0x0);

        distributeFee(totalFeeEth, refAddress);

        addUserTokens(msg.sender, tokenAmount);

        // the user is not going to receive any reward for the current purchase
        _core.addUserRewardPayouts(msg.sender, _data.getBonusPerShare() * tokenAmount);

        checkAndSendPromoBonus(ethAmount);
        
        updateTokenPrice(_core.convert256ToReal(tokenAmount));
        
        _core.trackBuy(msg.sender, ethAmount, tokenAmount);

        emit onTokenPurchase(msg.sender, ethAmount, tokenAmount, refAddress);
        
        return tokenAmount;
    }

    function setTotalSupply() internal {
        require(_data._totalSupply() == 0);

        uint256 tokenAmount = _token.balanceOf(address(this));

        _data.setTotalSupply(tokenAmount);
    }


    function checkAndSendPromoBonus(uint256 purchaseAmountEth) internal {
        if (purchaseAmountEth < _data.getPromoMinPurchaseEth()) return;

        if (getQuickPromoRemainingBlocks() == 0) sendQuickPromoBonus();
        if (getBigPromoRemainingBlocks() == 0) sendBigPromoBonus();
    }

    function sendQuickPromoBonus() internal {
        _core.payoutQuickBonus(msg.sender);

        emit onWinQuickPromo(msg.sender, _data.getCurrentQuickPromoBonus());
    }

    function sendBigPromoBonus() internal {
        _core.payoutBigBonus(msg.sender);

        emit onWinBigPromo(msg.sender, _data.getCurrentBigPromoBonus());
    }

    function distributeFee(uint256 totalFeeEth, address refAddress) internal {
        addProfitPerShare(totalFeeEth, refAddress);
        addDevReward(totalFeeEth);
        addTokenOwnerReward(totalFeeEth);
        addBigPromoBonus(totalFeeEth);
        addQuickPromoBonus(totalFeeEth);
    }

    function addProfitPerShare(uint256 totalFeeEth, address refAddress) internal {
        uint256 refBonus = calcRefBonus(totalFeeEth);
        uint256 totalShareReward = calcTotalShareRewardFee(totalFeeEth);

        if (refAddress != address(0x0)) {
            _core.addUserRefBalance.value(refBonus)(refAddress);
        } else {
            totalShareReward = SafeMath.add(totalShareReward, refBonus);
        }

        if (getTotalTokenSold() == 0) {
            _data.addTokenOwnerReward(totalShareReward);
        } else {
            _core.addBonusPerShare.value(totalShareReward)();
        }
    }

    function addDevReward(uint256 totalFeeEth) internal {
        _core.addDevReward.value(calcDevReward(totalFeeEth))();
    }    
    
    function addTokenOwnerReward(uint256 totalFeeEth) internal {
        _data.addTokenOwnerReward(calcTokenOwnerReward(totalFeeEth));
    }  

    function addBigPromoBonus(uint256 totalFeeEth) internal {
        _core.addBigPromoBonus.value(calcBigPromoBonus(totalFeeEth))();
    }

    function addQuickPromoBonus(uint256 totalFeeEth) internal {
        _core.addQuickPromoBonus.value(calcQuickPromoBonus(totalFeeEth))();
    }   


    function addUserTokens(address user, uint256 tokenAmount) internal {
        _core.addUserTokenLocalBalance(user, tokenAmount);
        _token.transfer(msg.sender, tokenAmount);   
    }

    function subUserTokens(address user, uint256 tokenAmount) internal {
        _core.subUserTokenLocalBalance(user, tokenAmount);
        _token.transferFrom(user, address(this), tokenAmount);    
    }

    function updateTokenPrice(int128 realTokenAmount) public {
        _data.setRealTokenPrice(calc1RealTokenRateFromRealTokens(realTokenAmount));
    }

    function ethToTokens(uint256 ethAmount, bool isBuy) internal view returns(uint256) {
        int128 realEthAmount = _core.convert256ToReal(ethAmount);
        int128 t0 = RealMath.div(realEthAmount, _data._realTokenPrice());
        int128 s = getRealPriceSpeed();

        int128 tn =  RealMath.div(t0, RealMath.toReal(100));

        for (uint i = 0; i < 100; i++) {

            int128 tns = RealMath.mul(tn, s);
            int128 exptns = RealMath.exp( RealMath.mul(tns, RealMath.toReal(isBuy ? int64(1) : int64(-1))) );

            int128 tn1 = RealMath.div(
                RealMath.mul( RealMath.mul(tns, tn), exptns ) + t0,
                RealMath.mul( exptns, RealMath.toReal(1) + tns )
            );

            if (RealMath.abs(tn-tn1) < RealMath.fraction(1, 1e18)) break;

            tn = tn1;
        }

        return _core.convertRealTo256(tn);
    }

    function tokensToEth(uint256 tokenAmount, bool isBuy) internal view returns(uint256) {
        int128 realTokenAmount = _core.convert256ToReal(tokenAmount);
        int128 s = getRealPriceSpeed();
        int128 expArg = RealMath.mul(RealMath.mul(realTokenAmount, s), RealMath.toReal(isBuy ? int64(1) : int64(-1)));
        
        int128 realEthAmountFor1Token = RealMath.mul(_data._realTokenPrice(), RealMath.exp(expArg));
        int128 realEthAmount = RealMath.mul(realTokenAmount, realEthAmountFor1Token);

        return _core.convertRealTo256(realEthAmount);
    }

    function calcTotalFee(uint256 tokenAmount, bool isBuy) internal view returns(uint256) {
        int128 realTokenAmount = _core.convert256ToReal(tokenAmount);
        int128 factor = RealMath.toReal(isBuy ? int64(1) : int64(-1));
        int128 rateAfterDeal = calc1RealTokenRateFromRealTokens(RealMath.mul(realTokenAmount, factor));
        int128 delta = RealMath.div(rateAfterDeal - _data._realTokenPrice(), RealMath.toReal(2));
        int128 fee = RealMath.mul(realTokenAmount, delta);
        
        //commission for sells is a bit lower due to rounding error
        if (!isBuy) fee = RealMath.mul(fee, RealMath.fraction(95, 100));

        return _core.calcPercent(_core.convertRealTo256(RealMath.mul(fee, factor)), _core._totalIncomeFeePercent());
    }



    function calc1RealTokenRateFromRealTokens(int128 realTokenAmount) internal view returns(int128) {
        int128 expArg = RealMath.mul(realTokenAmount, getRealPriceSpeed());

        return RealMath.mul(_data._realTokenPrice(), RealMath.exp(expArg));
    }
    
    function getRealPriceSpeed() internal view returns(int128) {
        require(RealMath.isUInt64ValidIn64(_data.PRICE_SPEED_PERCENT()));
        require(RealMath.isUInt64ValidIn64(_data.PRICE_SPEED_INTERVAL()));
        
        return RealMath.div(RealMath.fraction(int64(_data.PRICE_SPEED_PERCENT()), 100), RealMath.toReal(int64(_data.PRICE_SPEED_INTERVAL())));
    }


    function calcTotalShareRewardFee(uint256 totalFee) internal view returns(uint256) {
        return _core.calcPercent(totalFee, _core._shareRewardPercent());
    }
    
    function calcRefBonus(uint256 totalFee) internal view returns(uint256) {
        return _core.calcPercent(totalFee, _core._refBonusPercent());
    }
    
    function calcTokenOwnerReward(uint256 totalFee) internal view returns(uint256) {
        return _core.calcPercent(totalFee, _core._tokenOwnerRewardPercent());
    }

    function calcDevReward(uint256 totalFee) internal view returns(uint256) {
        return _core.calcPercent(totalFee, _core._devRewardPercent());
    }

    function calcQuickPromoBonus(uint256 totalFee) internal view returns(uint256) {
        return _core.calcPercent(totalFee, _core._quickPromoPercent());
    }    

    function calcBigPromoBonus(uint256 totalFee) internal view returns(uint256) {
        return _core.calcPercent(totalFee, _core._bigPromoPercent());
    }        


}


library SafeMath {

    /**
    * @dev Multiplies two numbers, throws on overflow.
    */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }
        uint256 c = a * b;
        assert(c / a == b);
        return c;
    }

    /**
    * @dev Integer division of two numbers, truncating the quotient.
    */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // assert(b > 0); // Solidity automatically throws when dividing by 0
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold
        return c;
    }

    /**
    * @dev Substracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
    */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        assert(b <= a);
        return a - b;
    }

    /**
    * @dev Adds two numbers, throws on overflow.
    */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        assert(c >= a);
        return c;
    } 

    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }   

    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? b : a;
    }   
}

//taken from https://github.com/NovakDistributed/macroverse/blob/master/contracts/RealMath.sol and a bit modified
library RealMath {
    
    int64 constant MIN_INT64 = int64((uint64(1) << 63));
    int64 constant MAX_INT64 = int64(~((uint64(1) << 63)));
    
    /**
     * How many total bits are there?
     */
    int256 constant REAL_BITS = 128;
    
    /**
     * How many fractional bits are there?
     */
    int256 constant REAL_FBITS = 64;
    
    /**
     * How many integer bits are there?
     */
    int256 constant REAL_IBITS = REAL_BITS - REAL_FBITS;
    
    /**
     * What's the first non-fractional bit
     */
    int128 constant REAL_ONE = int128(1) << REAL_FBITS;
    
    /**
     * What's the last fractional bit?
     */
    int128 constant REAL_HALF = REAL_ONE >> 1;
    
    /**
     * What's two? Two is pretty useful.
     */
    int128 constant REAL_TWO = REAL_ONE << 1;
    
    /**
     * And our logarithms are based on ln(2).
     */
    int128 constant REAL_LN_TWO = 762123384786;
    
    /**
     * It is also useful to have Pi around.
     */
    int128 constant REAL_PI = 3454217652358;
    
    /**
     * And half Pi, to save on divides.
     * TODO: That might not be how the compiler handles constants.
     */
    int128 constant REAL_HALF_PI = 1727108826179;
    
    /**
     * And two pi, which happens to be odd in its most accurate representation.
     */
    int128 constant REAL_TWO_PI = 6908435304715;
    
    /**
     * What's the sign bit?
     */
    int128 constant SIGN_MASK = int128(1) << 127;
    

    function getMinInt64() internal pure returns (int64) {
        return MIN_INT64;
    }
    
    function getMaxInt64() internal pure returns (int64) {
        return MAX_INT64;
    }
    
    function isUInt256ValidIn64(uint256 val) internal pure returns (bool) {
        return val >= 0 && val <= uint256(getMaxInt64());
    }
    
    function isInt256ValidIn64(int256 val) internal pure returns (bool) {
        return val >= int256(getMinInt64()) && val <= int256(getMaxInt64());
    }
    
    function isUInt64ValidIn64(uint64 val) internal pure returns (bool) {
        return val >= 0 && val <= uint64(getMaxInt64());
    }
    
    function isInt128ValidIn64(int128 val) internal pure returns (bool) {
        return val >= int128(getMinInt64()) && val <= int128(getMaxInt64());
    }

    /**
     * Convert an integer to a real. Preserves sign.
     */
    function toReal(int64 ipart) internal pure returns (int128) {
        return int128(ipart) * REAL_ONE;
    }
    
    /**
     * Convert a real to an integer. Preserves sign.
     */
    function fromReal(int128 real_value) internal pure returns (int64) {
        int128 intVal = real_value / REAL_ONE;
        require(isInt128ValidIn64(intVal));
        
        return int64(intVal);
    }
    
    
    /**
     * Get the absolute value of a real. Just the same as abs on a normal int128.
     */
    function abs(int128 real_value) internal pure returns (int128) {
        if (real_value > 0) {
            return real_value;
        } else {
            return -real_value;
        }
    }
    
    
    /**
     * Get the fractional part of a real, as a real. Ignores sign (so fpart(-0.5) is 0.5).
     */
    function fpart(int128 real_value) internal pure returns (int128) {
        // This gets the fractional part but strips the sign
        return abs(real_value) % REAL_ONE;
    }

    /**
     * Get the fractional part of a real, as a real. Respects sign (so fpartSigned(-0.5) is -0.5).
     */
    function fpartSigned(int128 real_value) internal pure returns (int128) {
        // This gets the fractional part but strips the sign
        int128 fractional = fpart(real_value);
        return real_value < 0 ? -fractional : fractional;
    }
    
    /**
     * Get the integer part of a fixed point value.
     */
    function ipart(int128 real_value) internal pure returns (int128) {
        // Subtract out the fractional part to get the real part.
        return real_value - fpartSigned(real_value);
    }
    
    /**
     * Multiply one real by another. Truncates overflows.
     */
    function mul(int128 real_a, int128 real_b) internal pure returns (int128) {
        // When multiplying fixed point in x.y and z.w formats we get (x+z).(y+w) format.
        // So we just have to clip off the extra REAL_FBITS fractional bits.
        return int128((int256(real_a) * int256(real_b)) >> REAL_FBITS);
    }
    
    /**
     * Divide one real by another real. Truncates overflows.
     */
    function div(int128 real_numerator, int128 real_denominator) internal pure returns (int128) {
        // We use the reverse of the multiplication trick: convert numerator from
        // x.y to (x+z).(y+w) fixed point, then divide by denom in z.w fixed point.
        return int128((int256(real_numerator) * REAL_ONE) / int256(real_denominator));
    }
    
    /**
     * Create a real from a rational fraction.
     */
    function fraction(int64 numerator, int64 denominator) internal pure returns (int128) {
        return div(toReal(numerator), toReal(denominator));
    }
    
    // Now we have some fancy math things (like pow and trig stuff). This isn't
    // in the RealMath that was deployed with the original Macroverse
    // deployment, so it needs to be linked into your contract statically.
    
    /**
     * Raise a number to a positive integer power in O(log power) time.
     * See <https://stackoverflow.com/a/101613>
     */
    function ipow(int128 real_base, int64 exponent) internal pure returns (int128) {
        if (exponent < 0) {
            // Negative powers are not allowed here.
            revert();
        }
        
        // Start with the 0th power
        int128 real_result = REAL_ONE;
        while (exponent != 0) {
            // While there are still bits set
            if ((exponent & 0x1) == 0x1) {
                // If the low bit is set, multiply in the (many-times-squared) base
                real_result = mul(real_result, real_base);
            }
            // Shift off the low bit
            exponent = exponent >> 1;
            // Do the squaring
            real_base = mul(real_base, real_base);
        }
        
        // Return the final result.
        return real_result;
    }
    
    /**
     * Zero all but the highest set bit of a number.
     * See <https://stackoverflow.com/a/53184>
     */
    function hibit(uint256 val) internal pure returns (uint256) {
        // Set all the bits below the highest set bit
        val |= (val >>  1);
        val |= (val >>  2);
        val |= (val >>  4);
        val |= (val >>  8);
        val |= (val >> 16);
        val |= (val >> 32);
        val |= (val >> 64);
        val |= (val >> 128);
        return val ^ (val >> 1);
    }
    
    /**
     * Given a number with one bit set, finds the index of that bit.
     */
    function findbit(uint256 val) internal pure returns (uint8 index) {
        index = 0;
        // We and the value with alternating bit patters of various pitches to find it.
        
        if (val & 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA != 0) {
            // Picth 1
            index |= 1;
        }
        if (val & 0xCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC != 0) {
            // Pitch 2
            index |= 2;
        }
        if (val & 0xF0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 != 0) {
            // Pitch 4
            index |= 4;
        }
        if (val & 0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00 != 0) {
            // Pitch 8
            index |= 8;
        }
        if (val & 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000 != 0) {
            // Pitch 16
            index |= 16;
        }
        if (val & 0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000 != 0) {
            // Pitch 32
            index |= 32;
        }
        if (val & 0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000 != 0) {
            // Pitch 64
            index |= 64;
        }
        if (val & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000 != 0) {
            // Pitch 128
            index |= 128;
        }
    }
    
    /**
     * Shift real_arg left or right until it is between 1 and 2. Return the
     * rescaled value, and the number of bits of right shift applied. Shift may be negative.
     *
     * Expresses real_arg as real_scaled * 2^shift, setting shift to put real_arg between [1 and 2).
     *
     * Rejects 0 or negative arguments.
     */
    function rescale(int128 real_arg) internal pure returns (int128 real_scaled, int64 shift) {
        if (real_arg <= 0) {
            // Not in domain!
            revert();
        }
        
        require(isInt256ValidIn64(REAL_FBITS));
        
        // Find the high bit
        int64 high_bit = findbit(hibit(uint256(real_arg)));
        
        // We'll shift so the high bit is the lowest non-fractional bit.
        shift = high_bit - int64(REAL_FBITS);
        
        if (shift < 0) {
            // Shift left
            real_scaled = real_arg << -shift;
        } else if (shift >= 0) {
            // Shift right
            real_scaled = real_arg >> shift;
        }
    }
    
    /**
     * Calculate the natural log of a number. Rescales the input value and uses
     * the algorithm outlined at <https://math.stackexchange.com/a/977836> and
     * the ipow implementation.
     *
     * Lets you artificially limit the number of iterations.
     *
     * Note that it is potentially possible to get an un-converged value; lack
     * of convergence does not throw.
     */
    function lnLimited(int128 real_arg, int max_iterations) internal pure returns (int128) {
        if (real_arg <= 0) {
            // Outside of acceptable domain
            revert();
        }
        
        if (real_arg == REAL_ONE) {
            // Handle this case specially because people will want exactly 0 and
            // not ~2^-39 ish.
            return 0;
        }
        
        // We know it's positive, so rescale it to be between [1 and 2)
        int128 real_rescaled;
        int64 shift;
        (real_rescaled, shift) = rescale(real_arg);
        
        // Compute the argument to iterate on
        int128 real_series_arg = div(real_rescaled - REAL_ONE, real_rescaled + REAL_ONE);
        
        // We will accumulate the result here
        int128 real_series_result = 0;
        
        for (int64 n = 0; n < max_iterations; n++) {
            // Compute term n of the series
            int128 real_term = div(ipow(real_series_arg, 2 * n + 1), toReal(2 * n + 1));
            // And add it in
            real_series_result += real_term;
            if (real_term == 0) {
                // We must have converged. Next term is too small to represent.
                break;
            }
            // If we somehow never converge I guess we will run out of gas
        }
        
        // Double it to account for the factor of 2 outside the sum
        real_series_result = mul(real_series_result, REAL_TWO);
        
        // Now compute and return the overall result
        return mul(toReal(shift), REAL_LN_TWO) + real_series_result;
        
    }
    
    /**
     * Calculate a natural logarithm with a sensible maximum iteration count to
     * wait until convergence. Note that it is potentially possible to get an
     * un-converged value; lack of convergence does not throw.
     */
    function ln(int128 real_arg) internal pure returns (int128) {
        return lnLimited(real_arg, 100);
    }
    

     /**
     * Calculate e^x. Uses the series given at
     * <http://pages.mtu.edu/~shene/COURSES/cs201/NOTES/chap04/exp.html>.
     *
     * Lets you artificially limit the number of iterations.
     *
     * Note that it is potentially possible to get an un-converged value; lack
     * of convergence does not throw.
     */
    function expLimited(int128 real_arg, int max_iterations) internal pure returns (int128) {
        // We will accumulate the result here
        int128 real_result = 0;
        
        // We use this to save work computing terms
        int128 real_term = REAL_ONE;
        
        for (int64 n = 0; n < max_iterations; n++) {
            // Add in the term
            real_result += real_term;
            
            // Compute the next term
            real_term = mul(real_term, div(real_arg, toReal(n + 1)));
            
            if (real_term == 0) {
                // We must have converged. Next term is too small to represent.
                break;
            }
            // If we somehow never converge I guess we will run out of gas
        }
        
        // Return the result
        return real_result;
        
    }

    function expLimited(int128 real_arg, int max_iterations, int k) internal pure returns (int128) {
        // We will accumulate the result here
        int128 real_result = 0;
        
        // We use this to save work computing terms
        int128 real_term = REAL_ONE;
        
        for (int64 n = 0; n < max_iterations; n++) {
            // Add in the term
            real_result += real_term;
            
            // Compute the next term
            real_term = mul(real_term, div(real_arg, toReal(n + 1)));
            
            if (real_term == 0) {
                // We must have converged. Next term is too small to represent.
                break;
            }

            if (n == k) return real_term;

            // If we somehow never converge I guess we will run out of gas
        }
        
        // Return the result
        return real_result;
        
    }

    /**
     * Calculate e^x with a sensible maximum iteration count to wait until
     * convergence. Note that it is potentially possible to get an un-converged
     * value; lack of convergence does not throw.
     */
    function exp(int128 real_arg) internal pure returns (int128) {
        return expLimited(real_arg, 100);
    }
    
    /**
     * Raise any number to any power, except for negative bases to fractional powers.
     */
    function pow(int128 real_base, int128 real_exponent) internal pure returns (int128) {
        if (real_exponent == 0) {
            // Anything to the 0 is 1
            return REAL_ONE;
        }
        
        if (real_base == 0) {
            if (real_exponent < 0) {
                // Outside of domain!
                revert();
            }
            // Otherwise it's 0
            return 0;
        }
        
        if (fpart(real_exponent) == 0) {
            // Anything (even a negative base) is super easy to do to an integer power.
            
            if (real_exponent > 0) {
                // Positive integer power is easy
                return ipow(real_base, fromReal(real_exponent));
            } else {
                // Negative integer power is harder
                return div(REAL_ONE, ipow(real_base, fromReal(-real_exponent)));
            }
        }
        
        if (real_base < 0) {
            // It's a negative base to a non-integer power.
            // In general pow(-x^y) is undefined, unless y is an int or some
            // weird rational-number-based relationship holds.
            revert();
        }
        
        // If it's not a special case, actually do it.
        return exp(mul(real_exponent, ln(real_base)));
    }
}

Contract Security Audit

Contract ABI

[{"constant":true,"inputs":[],"name":"getCurrentUserMaxPurchase","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getMinRefEthPurchase","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalTokenSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getPriceSpeedTokenBlock","outputs":[{"name":"","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"activate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentUserQuickPromoBonus","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTokenAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBlockNumSinceInit","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"realTokenAmount","type":"int128"}],"name":"updateTokenPrice","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"_core","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalVolumeEth","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isActive","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"amount","type":"uint256"},{"name":"fromEth","type":"bool"}],"name":"estimateBuyOrder","outputs":[{"name":"","type":"uint256"},{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"amount","type":"uint256"},{"name":"fromToken","type":"bool"}],"name":"estimateSellOrder","outputs":[{"name":"","type":"uint256"},{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalEthBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentUserLocalTokenBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTokenOwnerReward","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"migrateToNewNewControllerContract","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getTokenInitialPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalTokenSold","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getSellCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isMigrationToNewControllerInProgress","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getEthDealRange","outputs":[{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"addAdministator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentUserPromoBonus","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBigPromoRemainingBlocks","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"val","type":"bool"}],"name":"setHasMaxPurchaseLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newControllerAddr","type":"address"}],"name":"requestControllerContractMigration","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isCurrentUserRefAvailable","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isActualContractVer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"tokenAmount","type":"uint256"}],"name":"calcReward","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getPromoMinPurchaseEth","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getDataContractAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"migrationContractAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalCollectedPromoBonus","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_data","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBigPromoPercent","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentUserTotalPromoBonus","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getPriceSpeedPercent","outputs":[{"name":"","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"prepareForMigration","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"userAddress","type":"address"},{"name":"isTotal","type":"bool"}],"name":"getUserReward","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getRemainingTokenAmount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"removeAdministator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getMaxGasPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"userAddress","type":"address"}],"name":"getUserMaxPurchase","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBuyCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentUserBigPromoBonus","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getShareRewardPercent","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getDevRewardPercent","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"migrateFunds","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"getTokenDealRange","outputs":[{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getRemainingTimeTillExpiration","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"transferOwnershipRequest","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getBonusPerShare","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getRefBonusPercent","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"get1TokenBuyPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"approveControllerContractMigration","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getTotalVolumeToken","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getQuickPromoBlockInterval","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isCurrentUserAdministrator","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"toUser","type":"address"},{"name":"tokenAmount","type":"uint256"}],"name":"transferTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getTokenOwnerRewardPercent","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentUserRefBonus","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentQuickPromoBonus","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentBigPromoBonus","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"refAddress","type":"address"},{"name":"minReturn","type":"uint256"}],"name":"buy","outputs":[{"name":"","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"userAddress","type":"address"}],"name":"getUserLocalTokenBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"finish","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"tokenAmount","type":"uint256"},{"name":"minReturn","type":"uint256"}],"name":"sell","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getExpirationTime","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_token","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"withdrawTokenOwnerReward","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getBigPromoBlockInterval","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getQuickPromoPercent","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getQuickPromoRemainingBlocks","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isMigrationApproved","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentTokenPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"get1TokenSellPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"dataContractAddress","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"userAddress","type":"address"},{"indexed":false,"name":"incomingEth","type":"uint256"},{"indexed":false,"name":"tokensMinted","type":"uint256"},{"indexed":true,"name":"referredBy","type":"address"}],"name":"onTokenPurchase","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"userAddress","type":"address"},{"indexed":false,"name":"tokensBurned","type":"uint256"},{"indexed":false,"name":"ethEarned","type":"uint256"}],"name":"onTokenSell","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"userAddress","type":"address"},{"indexed":false,"name":"ethReinvested","type":"uint256"},{"indexed":false,"name":"tokensMinted","type":"uint256"}],"name":"onReinvestment","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"toAddress","type":"address"},{"indexed":false,"name":"ethWithdrawn","type":"uint256"}],"name":"onWithdrawTokenOwnerReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"userAddress","type":"address"},{"indexed":false,"name":"ethWon","type":"uint256"}],"name":"onWinQuickPromo","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"userAddress","type":"address"},{"indexed":false,"name":"ethWon","type":"uint256"}],"name":"onWinBigPromo","type":"event"}]

60806040526002805460a060020a62ffffff02191676010000000000000000000000000000000000000000000017905560038054600160a860020a031916905560048054600160a060020a03191690553480156200005c57600080fd5b50604051602080620055248339810160405251600160a060020a03811615156200008557600080fd5b60018054600160a060020a031916600160a060020a038381169190911791829055604080517ffcc60b6a0000000000000000000000000000000000000000000000000000000081529051929091169163fcc60b6a916004808201926020929091908290030181600087803b158015620000fd57600080fd5b505af115801562000112573d6000803e3d6000fd5b505050506040513d60208110156200012957600080fd5b505115156200024a57600160009054906101000a9004600160a060020a0316600160a060020a031663e1c7392a6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401600060405180830381600087803b1580156200019f57600080fd5b505af1158015620001b4573d6000803e3d6000fd5b5050600154604080517f3dc19db80000000000000000000000000000000000000000000000000000000081523360048201529051600160a060020a039092169350633dc19db8925060248082019260009290919082900301818387803b1580156200021e57600080fd5b505af115801562000233573d6000803e3d6000fd5b505060048054600160a060020a0319163317905550505b600160009054906101000a9004600160a060020a0316600160a060020a031663ecd0c0c36040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015620002b757600080fd5b505af1158015620002cc573d6000803e3d6000fd5b505050506040513d6020811015620002e357600080fd5b505160008054600160a060020a031916600160a060020a03928316178155600154604080517f1460e1c200000000000000000000000000000000000000000000000000000000815290519190931692631460e1c29260048083019360209390929083900390910190829087803b1580156200035d57600080fd5b505af115801562000372573d6000803e3d6000fd5b505050506040513d60208110156200038957600080fd5b505160028054600160a060020a031916600160a060020a039092169190911790555061516980620003bb6000396000f3006080604052600436106103815763ffffffff60e060020a60003504166301d90bbc811461044157806303e07b2f14610468578063047087cc1461047d57806309b230cd146104925780630f15f4c0146104c45780630f9bb8b3146104db57806310fe9ae8146104f057806311a153df14610521578063134a5330146105365780631460e1c21461055157806316035ba01461056657806322f3e2d41461057b5780632561ee35146105a4578063258dd544146105df578063287cc96b146105fc57806329a52db6146106115780632a827f99146106265780632d1394171461063b5780632e58e65a146106505780632ecd702014610665578063345160381461067a57806335060b0c1461068f5780633802a4a2146106a45780633dc19db8146106d25780633f8a04aa146106f357806345a48de6146107085780634a0d8b531461071d5780634ab1c98f146107375780634b6ad918146107585780634c9e929d1461076d578063544c465c1461078257806354cb50811461079a57806361e91ea1146107af578063646d7a98146107c457806365863b24146107d957806368beab3f146107ee5780636984d4a8146108035780636b57825c146106f35780636da4edff1461081857806373d01ead1461082d57806379ba5097146108425780637a2c85061461085757806383af3c401461087d57806389c7abfd1461089257806389c98c06146108b357806389dc8719146108c85780638f10fd45146108e957806390d2cd5c146108fe578063921710e914610913578063951d6c9c146109285780639580c4bc1461093d578063a239392214610945578063a3bdc6551461095a578063a5d638f11461096f578063a67c273014610990578063b1fc756f146109a5578063b21cee7d146109ba578063b63df2a0146109cf578063b768ce60146109e4578063b809127e146109f9578063bb1b99ce14610a0e578063bec3fa1714610a23578063c0a3634514610a47578063c0a843a114610a5c578063ca2c139c14610a71578063cc45158114610a86578063cce7ec1314610a9b578063d2c3762114610ab2578063d56b288914610ad3578063d79875eb14610ae8578063e23a845a14610b03578063ecd0c0c314610b18578063eff134ee14610b2d578063f2139abf14610b42578063f27c85bc14610b57578063f34d22d014610b6c578063f6dbee1e14610b81578063f751758b14610b96578063ff60cdf614610bab575b60025460a060020a900460ff16151561039957600080fd5b600260009054906101000a9004600160a060020a0316600160a060020a031663e3bbb4f16040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156103ec57600080fd5b505af1158015610400573d6000803e3d6000fd5b505050506040513d602081101561041657600080fd5b50513a111561042457600080fd5b6000341161043157600080fd5b61043e3460006001610bc0565b50005b34801561044d57600080fd5b50610456610ff3565b60408051918252519081900360200190f35b34801561047457600080fd5b50610456611004565b34801561048957600080fd5b50610456611094565b34801561049e57600080fd5b506104a76110f3565b6040805167ffffffffffffffff9092168252519081900360200190f35b3480156104d057600080fd5b506104d9611152565b005b3480156104e757600080fd5b506104566111e7565b3480156104fc57600080fd5b5061050561124c565b60408051600160a060020a039092168252519081900360200190f35b34801561052d57600080fd5b5061045661125b565b34801561054257600080fd5b506104d9600435600f0b6112ba565b34801561055d57600080fd5b5061050561132e565b34801561057257600080fd5b5061045661133d565b34801561058757600080fd5b506105906113a4565b604080519115158252519081900360200190f35b3480156105b057600080fd5b506105c160043560243515156113b4565b60408051938452602084019290925282820152519081900360600190f35b3480156105eb57600080fd5b506105c16004356024351515611474565b34801561060857600080fd5b50610456611519565b34801561061d57600080fd5b5061045661151e565b34801561063257600080fd5b50610456611529565b34801561064757600080fd5b506104d9611588565b34801561065c57600080fd5b506104566117e0565b34801561067157600080fd5b5061045661183f565b34801561068657600080fd5b50610456611857565b34801561069b57600080fd5b50610590611873565b3480156106b057600080fd5b506106b9611895565b6040805192835260208301919091528051918290030190f35b3480156106de57600080fd5b506104d9600160a060020a03600435166119ef565b3480156106ff57600080fd5b50610456611a69565b34801561071457600080fd5b50610456611ace565b34801561072957600080fd5b506104d96004351515611b2d565b34801561074357600080fd5b506104d9600160a060020a0360043516611ba7565b34801561076457600080fd5b50610590611c00565b34801561077957600080fd5b50610590611c5f565b34801561078e57600080fd5b50610456600435611c82565b3480156107a657600080fd5b50610456611dab565b3480156107bb57600080fd5b50610505611e0a565b3480156107d057600080fd5b50610505611e19565b3480156107e557600080fd5b50610456611e28565b3480156107fa57600080fd5b50610505611e87565b34801561080f57600080fd5b50610456611e96565b34801561082457600080fd5b506104a7611ef5565b34801561083957600080fd5b506104d9611f54565b34801561084e57600080fd5b506104d9611fc9565b34801561086357600080fd5b50610456600160a060020a03600435166024351515612095565b34801561088957600080fd5b506104566121f7565b34801561089e57600080fd5b506104d9600160a060020a036004351661225d565b3480156108bf57600080fd5b506104566122d7565b3480156108d457600080fd5b50610456600160a060020a0360043516612336565b3480156108f557600080fd5b506104566123e9565b34801561090a57600080fd5b50610456612405565b34801561091f57600080fd5b5061045661246a565b34801561093457600080fd5b506104566124c9565b6104d9612528565b34801561095157600080fd5b506106b9612552565b34801561096657600080fd5b50610456612669565b34801561097b57600080fd5b506104d9600160a060020a03600435166127a7565b34801561099c57600080fd5b506104566127c6565b3480156109b157600080fd5b506104566128df565b3480156109c657600080fd5b5061045661293e565b3480156109db57600080fd5b506104d961297b565b3480156109f057600080fd5b50610456612a3e565b348015610a0557600080fd5b50610456612a5a565b348015610a1a57600080fd5b50610590612afc565b348015610a2f57600080fd5b506104d9600160a060020a0360043516602435612b61565b348015610a5357600080fd5b50610456612d53565b348015610a6857600080fd5b50610456612db2565b348015610a7d57600080fd5b50610456612e17565b348015610a9257600080fd5b50610456612e76565b610456600160a060020a0360043516602435612ed5565b348015610abe57600080fd5b50610456600160a060020a0360043516612f93565b348015610adf57600080fd5b506104d9613030565b348015610af457600080fd5b506104566004356024356131e3565b348015610b0f57600080fd5b50610456613544565b348015610b2457600080fd5b506105056135de565b348015610b3957600080fd5b506104d96135ed565b348015610b4e57600080fd5b506104566136eb565b348015610b6357600080fd5b5061045661374a565b348015610b7857600080fd5b506104566137a9565b348015610b8d57600080fd5b50610590613808565b348015610ba257600080fd5b50610456613818565b348015610bb757600080fd5b506104566138f4565b6000808080610bd08760016113b4565b9194509250905084831015610be457600080fd5b600160009054906101000a9004600160a060020a0316600160a060020a0316631e4f7dd36040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015610c3757600080fd5b505af1158015610c4b573d6000803e3d6000fd5b505050506040513d6020811015610c6157600080fd5b505115610c7c5782610c71610ff3565b1015610c7c57600080fd5b600083118015610ca25750610c8f61183f565b610ca084610c9b61183f565b613919565b115b1515610cad57600080fd5b600160a060020a038616331480610d555750600254604080517ff8ab02dd000000000000000000000000000000000000000000000000000000008152600160a060020a0389811660048301529151919092169163f8ab02dd9160248083019260209291908290030181600087803b158015610d2757600080fd5b505af1158015610d3b573d6000803e3d6000fd5b505050506040513d6020811015610d5157600080fd5b5051155b15610d5f57600095505b610d698287613933565b610d733384613965565b600254600154604080517fa67c27300000000000000000000000000000000000000000000000000000000081529051600160a060020a039384169363f8a0cdee9333938993919092169163a67c27309160048083019260209291908290030181600087803b158015610de457600080fd5b505af1158015610df8573d6000803e3d6000fd5b505050506040513d6020811015610e0e57600080fd5b50516040805160e060020a63ffffffff8716028152600160a060020a0390941660048501529102602483015251604480830192600092919082900301818387803b158015610e5b57600080fd5b505af1158015610e6f573d6000803e3d6000fd5b50505050610e7c87613a59565b600254604080517f1e2273a7000000000000000000000000000000000000000000000000000000008152600481018690529051610f1592600160a060020a031691631e2273a79160248083019260209291908290030181600087803b158015610ee457600080fd5b505af1158015610ef8573d6000803e3d6000fd5b505050506040513d6020811015610f0e57600080fd5b50516112ba565b600254604080517f80870bc1000000000000000000000000000000000000000000000000000000008152336004820152602481018a9052604481018690529051600160a060020a03909216916380870bc19160648082019260009290919082900301818387803b158015610f8857600080fd5b505af1158015610f9c573d6000803e3d6000fd5b5050604080518a8152602081018790528151600160a060020a038b1694503393507f022c0d992e4d873a3748436d960d5140c1f9721cf73f7ca5ec679d3d9f4fe2d5929181900390910190a3509095945050505050565b6000610ffe33612336565b90505b90565b600254604080517f84e221c60000000000000000000000000000000000000000000000000000000081529051600092600160a060020a0316916384e221c691600480830192602092919082900301818787803b15801561106357600080fd5b505af1158015611077573d6000803e3d6000fd5b505050506040513d602081101561108d57600080fd5b5051905090565b600154604080517f3eaaf86b0000000000000000000000000000000000000000000000000000000081529051600092600160a060020a031691633eaaf86b91600480830192602092919082900301818787803b15801561106357600080fd5b600154604080517fd5562acd0000000000000000000000000000000000000000000000000000000081529051600092600160a060020a03169163d5562acd91600480830192602092919082900301818787803b15801561106357600080fd5b61115a612afc565b151561116557600080fd5b60025460a060020a900460ff161561117c57600080fd5b611184611094565b151561119257611192613b10565b600061119c611094565b116111a657600080fd5b6002805475ff0000000000000000000000000000000000000000001974ff00000000000000000000000000000000000000001990911660a060020a17169055565b600154604080517f05af01940000000000000000000000000000000000000000000000000000000081523360048201529051600092600160a060020a0316916305af019491602480830192602092919082900301818787803b15801561106357600080fd5b600054600160a060020a031690565b600254604080517f11a153df0000000000000000000000000000000000000000000000000000000081529051600092600160a060020a0316916311a153df91600480830192602092919082900301818787803b15801561106357600080fd5b600154600160a060020a031663efbd863e6112d483613ca1565b6040518263ffffffff1660e060020a0281526004018082600f0b600f0b8152602001915050600060405180830381600087803b15801561131357600080fd5b505af1158015611327573d6000803e3d6000fd5b5050505050565b600254600160a060020a031681565b600254600090600160a060020a03166398163597611359611e0a565b6040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b15801561106357600080fd5b60025460a060020a900460ff1681565b6000806000806000806000806000896113d4576113cf612552565b6113dc565b6113dc611895565b9096509450896113f6576113f18b6001613d42565b6113f8565b8a5b93506000841161140757600080fd5b89611412578a61141d565b61141d8b6001613f46565b925061142a8360016141e1565b915081841161143857600080fd5b61144c84670de0b6b3a764000002846144af565b9050896114625761145d8483613919565b611464565b825b9b919a5098509650505050505050565b6000806000806000806000806000896114945761148f611895565b61149c565b61149c612552565b9096509450896114b6576114b18b6000613f46565b6114b8565b8a5b9350600084116114c757600080fd5b896114d2578a6114dd565b6114dd846000613d42565b92506114ea8460006141e1565b91508183116114f857600080fd5b61150c83670de0b6b3a764000002856144af565b9050896114625783611464565b303190565b6000610ffe33612f93565b600154604080517f83325a1d0000000000000000000000000000000000000000000000000000000081529051600092600160a060020a0316916383325a1d91600480830192602092919082900301818787803b15801561106357600080fd5b6000806000611595612afc565b15156115a057600080fd5b60035460a060020a900460ff1680156115c35750600354600160a060020a031615155b80156115eb5750600254760100000000000000000000000000000000000000000000900460ff165b15156115f657600080fd5b6002805474ff000000000000000000000000000000000000000019169055600354600154604080517f717e9745000000000000000000000000000000000000000000000000000000008152600160a060020a03938416600482018190529151919650929091169163717e974591602480830192600092919082900301818387803b15801561168357600080fd5b505af1158015611697573d6000803e3d6000fd5b505050506116a36121f7565b91506116ad611519565b9050600082111561175a5760008054600354604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a039283166004820152602481018790529051919092169263a9059cbb92604480820193602093909283900390910190829087803b15801561172d57600080fd5b505af1158015611741573d6000803e3d6000fd5b505050506040513d602081101561175757600080fd5b50505b60008111156117bb5782600160a060020a0316639580c4bc826040518263ffffffff1660e060020a0281526004016000604051808303818588803b1580156117a157600080fd5b505af11580156117b5573d6000803e3d6000fd5b50505050505b50506002805476ff000000000000000000000000000000000000000000001916905550565b600154604080517ffc0c8c980000000000000000000000000000000000000000000000000000000081529051600092600160a060020a03169163fc0c8c9891600480830192602092919082900301818787803b15801561106357600080fd5b60006118496121f7565b611851611094565b03905090565b600254600090600160a060020a031663cfc5e7c8611359611e0a565b6002547501000000000000000000000000000000000000000000900460ff1681565b6000806000806118a3612552565b600254604080517f84ad5024000000000000000000000000000000000000000000000000000000008152905193955091935061194892600160a060020a03909116916384ad50249160048083019260209291908290030181600087803b15801561190c57600080fd5b505af1158015611920573d6000803e3d6000fd5b505050506040513d602081101561193657600080fd5b5051611943846001613d42565b6144c6565b600254604080517fb1b6f19e00000000000000000000000000000000000000000000000000000000815290516119e592600160a060020a03169163b1b6f19e9160048083019260209291908290030181600087803b1580156119a957600080fd5b505af11580156119bd573d6000803e3d6000fd5b505050506040513d60208110156119d357600080fd5b50516119e0846001613d42565b6144db565b9350935050509091565b6119f7612afc565b1515611a0257600080fd5b600154604080517f3dc19db8000000000000000000000000000000000000000000000000000000008152600160a060020a03848116600483015291519190921691633dc19db891602480830192600092919082900301818387803b15801561131357600080fd5b600154604080517f64004ea50000000000000000000000000000000000000000000000000000000081523360048201529051600092600160a060020a0316916364004ea591602480830192602092919082900301818787803b15801561106357600080fd5b600254604080517f45a48de60000000000000000000000000000000000000000000000000000000081529051600092600160a060020a0316916345a48de691600480830192602092919082900301818787803b15801561106357600080fd5b611b35612afc565b1515611b4057600080fd5b600154604080517f4a0d8b5300000000000000000000000000000000000000000000000000000000815283151560048201529051600160a060020a0390921691634a0d8b539160248082019260009290919082900301818387803b15801561131357600080fd5b611baf612afc565b1515611bba57600080fd5b60035460a060020a900460ff1615611bd157600080fd5b6003805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600254604080517f6860dc1f0000000000000000000000000000000000000000000000000000000081529051600092600160a060020a031691636860dc1f91600480830192602092919082900301818787803b15801561106357600080fd5b600254760100000000000000000000000000000000000000000000900460ff1681565b600254604080517f6d3036a70000000000000000000000000000000000000000000000000000000081529051600092600160a060020a031691636d3036a791600480830192602092919082900301818787803b158015611ce157600080fd5b505af1158015611cf5573d6000803e3d6000fd5b505050506040513d6020811015611d0b57600080fd5b5051600154604080517fa67c273000000000000000000000000000000000000000000000000000000000815290518592600160a060020a03169163a67c27309160048083019260209291908290030181600087803b158015611d6c57600080fd5b505af1158015611d80573d6000803e3d6000fd5b505050506040513d6020811015611d9657600080fd5b505102811515611da257fe5b0490505b919050565b600254604080517ff7c561590000000000000000000000000000000000000000000000000000000081529051600092600160a060020a03169163f7c5615991600480830192602092919082900301818787803b15801561106357600080fd5b600154600160a060020a031690565b600354600160a060020a031681565b600154604080517f65863b240000000000000000000000000000000000000000000000000000000081529051600092600160a060020a0316916365863b2491600480830192602092919082900301818787803b15801561106357600080fd5b600154600160a060020a031681565b600254604080517fa37fdf7f0000000000000000000000000000000000000000000000000000000081529051600092600160a060020a03169163a37fdf7f91600480830192602092919082900301818787803b15801561106357600080fd5b600154604080517f709d94460000000000000000000000000000000000000000000000000000000081529051600092600160a060020a03169163709d944691600480830192602092919082900301818787803b15801561106357600080fd5b611f5c612afc565b1515611f6757600080fd5b6002547501000000000000000000000000000000000000000000900460ff1615611f9057600080fd5b6002805475ff00000000000000000000000000000000000000000019167501000000000000000000000000000000000000000000179055565b611fd1612afc565b1515611fdc57600080fd5b600454600160a060020a03161515611ff357600080fd5b60045461200890600160a060020a031661225d565b600160009054906101000a9004600160a060020a0316600160a060020a031663940a6cf56040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561205b57600080fd5b505af115801561206f573d6000803e3d6000fd5b505050506040513d602081101561208557600080fd5b505160011461209357600080fd5b565b6000816121465760018054604080517f33512aa9000000000000000000000000000000000000000000000000000000008152600160a060020a038781166004830152602482018590526044820194909452905192909116916333512aa9916064808201926020929091908290030181600087803b15801561211557600080fd5b505af1158015612129573d6000803e3d6000fd5b505050506040513d602081101561213f57600080fd5b50516121f0565b600254604080517f854772ea000000000000000000000000000000000000000000000000000000008152600160a060020a0386811660048301526001602483018190526044830181905260648301529151919092169163854772ea9160848083019260209291908290030181600087803b1580156121c357600080fd5b505af11580156121d7573d6000803e3d6000fd5b505050506040513d60208110156121ed57600080fd5b50515b9392505050565b60008054604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051600160a060020a03909216916370a082319160248082019260209290919082900301818787803b15801561106357600080fd5b612265612afc565b151561227057600080fd5b600154604080517f89c7abfd000000000000000000000000000000000000000000000000000000008152600160a060020a038481166004830152915191909216916389c7abfd91602480830192600092919082900301818387803b15801561131357600080fd5b600254604080517fe3bbb4f10000000000000000000000000000000000000000000000000000000081529051600092600160a060020a03169163e3bbb4f191600480830192602092919082900301818787803b15801561106357600080fd5b600061234b61234483612f93565b60026144f1565b60008054604080517f70a08231000000000000000000000000000000000000000000000000000000008152600160a060020a038781166004830152915191909216926370a0823192602480820193602093909283900390910190829087803b1580156123b657600080fd5b505af11580156123ca573d6000803e3d6000fd5b505050506040513d60208110156123e057600080fd5b50510392915050565b600254600090600160a060020a031663d489c0bf611359611e0a565b600154604080517fe4fe8eb10000000000000000000000000000000000000000000000000000000081523360048201529051600092600160a060020a03169163e4fe8eb191602480830192602092919082900301818787803b15801561106357600080fd5b600254604080517f1bde12480000000000000000000000000000000000000000000000000000000081529051600092600160a060020a031691631bde124891600480830192602092919082900301818787803b15801561106357600080fd5b600254604080517f584451f20000000000000000000000000000000000000000000000000000000081529051600092600160a060020a03169163584451f291600480830192602092919082900301818787803b15801561106357600080fd5b6002547501000000000000000000000000000000000000000000900460ff16151561209357600080fd5b600080600260009054906101000a9004600160a060020a0316600160a060020a031663627e25b16040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156125a857600080fd5b505af11580156125bc573d6000803e3d6000fd5b505050506040513d60208110156125d257600080fd5b5051600254604080517fa66be4780000000000000000000000000000000000000000000000000000000081529051600160a060020a039092169163a66be478916004808201926020929091908290030181600087803b15801561263457600080fd5b505af1158015612648573d6000803e3d6000fd5b505050506040513d602081101561265e57600080fd5b505190925090509091565b60004267ffffffffffffffff16600160009054906101000a9004600160a060020a0316600160a060020a031663772dda6a6040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156126c957600080fd5b505af11580156126dd573d6000803e3d6000fd5b505050506040513d60208110156126f357600080fd5b505167ffffffffffffffff161161270c57506000611001565b600154604080517f772dda6a00000000000000000000000000000000000000000000000000000000815290514292600160a060020a03169163772dda6a9160048083019260209291908290030181600087803b15801561276b57600080fd5b505af115801561277f573d6000803e3d6000fd5b505050506040513d602081101561279557600080fd5b50510367ffffffffffffffff16919050565b6127af612afc565b15156127ba57600080fd5b6127c3816119ef565b50565b6000610ffe61285b600160009054906101000a9004600160a060020a0316600160a060020a031663a67c27306040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561282157600080fd5b505af1158015612835573d6000803e3d6000fd5b505050506040513d602081101561284b57600080fd5b5051670de0b6b3a76400006144f1565b600260009054906101000a9004600160a060020a0316600160a060020a0316636d3036a76040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156128ae57600080fd5b505af11580156128c2573d6000803e3d6000fd5b505050506040513d60208110156128d857600080fd5b50516144af565b600254604080517f111081f80000000000000000000000000000000000000000000000000000000081529051600092600160a060020a03169163111081f891600480830192602092919082900301818787803b15801561106357600080fd5b6000670de0b6b3a76400008180806129578460016113b4565b91945092509050612972670de0b6b3a76400008502846144af565b94505050505090565b600254604080517f0a2eb3010000000000000000000000000000000000000000000000000000000081523360048201529051600160a060020a0390921691630a2eb301916024808201926020929091908290030181600087803b1580156129e157600080fd5b505af11580156129f5573d6000803e3d6000fd5b505050506040513d6020811015612a0b57600080fd5b50511515612a1857600080fd5b6003805474ff0000000000000000000000000000000000000000191660a060020a179055565b600254600090600160a060020a0316639455924f611359611e0a565b600254604080517fe2c0d1dc0000000000000000000000000000000000000000000000000000000081529051600092600160a060020a03169163e2c0d1dc91600480830192602092919082900301818787803b158015612ab957600080fd5b505af1158015612acd573d6000803e3d6000fd5b505050506040513d6020811015612ae357600080fd5b50516fffffffffffffffffffffffffffffffff16905090565b600154604080517f0a2eb3010000000000000000000000000000000000000000000000000000000081523360048201529051600092600160a060020a031691630a2eb30191602480830192602092919082900301818787803b15801561106357600080fd5b60025460a060020a900460ff161515612b7957600080fd5b6000612b8433612f93565b11612b8e57600080fd5b80612b9833612f93565b1015612ba357600080fd5b600254604080517f7442f427000000000000000000000000000000000000000000000000000000008152336004820152602481018490529051600160a060020a0390921691637442f4279160448082019260009290919082900301818387803b158015612c0f57600080fd5b505af1158015612c23573d6000803e3d6000fd5b5050600254604080517fa731c4ec000000000000000000000000000000000000000000000000000000008152600160a060020a03878116600483015260248201879052915191909216935063a731c4ec9250604480830192600092919082900301818387803b158015612c9557600080fd5b505af1158015612ca9573d6000803e3d6000fd5b505060008054604080517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152600160a060020a0388811660248301526044820188905291519190921694506323b872dd935060648083019360209383900390910190829087803b158015612d2357600080fd5b505af1158015612d37573d6000803e3d6000fd5b505050506040513d6020811015612d4d57600080fd5b50505050565b600254604080517f44c403670000000000000000000000000000000000000000000000000000000081529051600092600160a060020a0316916344c4036791600480830192602092919082900301818787803b15801561106357600080fd5b600154604080517f24bdf96a0000000000000000000000000000000000000000000000000000000081523360048201529051600092600160a060020a0316916324bdf96a91602480830192602092919082900301818787803b15801561106357600080fd5b600154604080517fca2c139c0000000000000000000000000000000000000000000000000000000081529051600092600160a060020a03169163ca2c139c91600480830192602092919082900301818787803b15801561106357600080fd5b600154604080517fcc4515810000000000000000000000000000000000000000000000000000000081529051600092600160a060020a03169163cc45158191600480830192602092919082900301818787803b15801561106357600080fd5b60025460009060a060020a900460ff161515612ef057600080fd5b600260009054906101000a9004600160a060020a0316600160a060020a031663e3bbb4f16040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015612f4357600080fd5b505af1158015612f57573d6000803e3d6000fd5b505050506040513d6020811015612f6d57600080fd5b50513a1115612f7b57600080fd5b60003411612f8857600080fd5b6121f0348484610bc0565b600154604080517ffc6ef5a5000000000000000000000000000000000000000000000000000000008152600160a060020a0384811660048301529151600093929092169163fc6ef5a59160248082019260209290919082900301818787803b158015612ffe57600080fd5b505af1158015613012573d6000803e3d6000fd5b505050506040513d602081101561302857600080fd5b505192915050565b60025460a060020a900460ff16151561304857600080fd5b613050612afc565b151561305b57600080fd5b600160009054906101000a9004600160a060020a0316600160a060020a031663772dda6a6040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156130ae57600080fd5b505af11580156130c2573d6000803e3d6000fd5b505050506040513d60208110156130d857600080fd5b505167ffffffffffffffff9081164290911610156130f557600080fd5b600054600160a060020a031663a9059cbb3361310f6121f7565b6040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050602060405180830381600087803b15801561316157600080fd5b505af1158015613175573d6000803e3d6000fd5b505050506040513d602081101561318b57600080fd5b503390506108fc61319a611519565b6040518115909202916000818181858888f193505050501580156131c2573d6000803e3d6000fd5b506002805474ff000000000000000000000000000000000000000019169055565b6000806000806000600260149054906101000a900460ff16151561320657600080fd5b600061321133612f93565b1161321b57600080fd5b600260009054906101000a9004600160a060020a0316600160a060020a031663e3bbb4f16040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561326e57600080fd5b505af1158015613282573d6000803e3d6000fd5b505050506040513d602081101561329857600080fd5b50513a11156132a657600080fd5b6132ae61151e565b8711806132b9575086155b156132c7576000945061353a565b6000935060009250600091506132de876001611474565b91955093509150858410156132f257600080fd5b6132fc338861451c565b604051339085156108fc029086906000818181858888f19350505050158015613329573d6000803e3d6000fd5b50600254604080517f1e2273a7000000000000000000000000000000000000000000000000000000008152600481018a905290516133c692600160a060020a031691631e2273a79160248083019260209291908290030181600087803b15801561339257600080fd5b505af11580156133a6573d6000803e3d6000fd5b505050506040513d60208110156133bc57600080fd5b50516000036112ba565b6133d1836000613933565b600154604080517fa50097f20000000000000000000000000000000000000000000000000000000081523360048201529051600160a060020a039092169163a50097f2916024808201926020929091908290030181600087803b15801561343757600080fd5b505af115801561344b573d6000803e3d6000fd5b505050506040513d602081101561346157600080fd5b5051600254909150600160a060020a031663aff7bd49338387116134855786613487565b835b8a6040518463ffffffff1660e060020a0281526004018084600160a060020a0316600160a060020a031681526020018381526020018281526020019350505050600060405180830381600087803b1580156134e157600080fd5b505af11580156134f5573d6000803e3d6000fd5b5050604080518a81526020810188905281513394507fc4823739c5787d2ca17e404aa47d5569ae71dfb49cbf21b3f6152ed238a3113993509081900390910190a28394505b5050505092915050565b600154604080517f772dda6a0000000000000000000000000000000000000000000000000000000081529051600092600160a060020a03169163772dda6a91600480830192602092919082900301818787803b1580156135a357600080fd5b505af11580156135b7573d6000803e3d6000fd5b505050506040513d60208110156135cd57600080fd5b505167ffffffffffffffff16905090565b600054600160a060020a031681565b60006135f7612afc565b151561360257600080fd5b61360a611529565b90506000811161361957600080fd5b600160009054906101000a9004600160a060020a0316600160a060020a03166398f44c626040518163ffffffff1660e060020a028152600401600060405180830381600087803b15801561366c57600080fd5b505af1158015613680573d6000803e3d6000fd5b505060405133925083156108fc02915083906000818181858888f193505050501580156136b1573d6000803e3d6000fd5b5060408051828152905133917f1ba011e09f28433d9daa82720a744c226d955ca94ce44c0904b60de5445713fb919081900360200190a250565b600254604080517f707c5c4c0000000000000000000000000000000000000000000000000000000081529051600092600160a060020a03169163707c5c4c91600480830192602092919082900301818787803b158015612ab957600080fd5b600254604080517f69ae4de00000000000000000000000000000000000000000000000000000000081529051600092600160a060020a0316916369ae4de091600480830192602092919082900301818787803b15801561106357600080fd5b600254604080517ff34d22d00000000000000000000000000000000000000000000000000000000081529051600092600160a060020a03169163f34d22d091600480830192602092919082900301818787803b15801561106357600080fd5b60035460a060020a900460ff1681565b600254600154604080517f01f0e6ad0000000000000000000000000000000000000000000000000000000081529051600093600160a060020a039081169363d8fcfd6b939116916301f0e6ad9160048082019260209290919082900301818987803b15801561388657600080fd5b505af115801561389a573d6000803e3d6000fd5b505050506040513d60208110156138b057600080fd5b50516040805160e060020a63ffffffff8516028152600f92830b90920b60048301525160248083019260209291908290030181600087803b15801561106357600080fd5b6000670de0b6b3a764000081808061390d846001611474565b50909695505050505050565b60008282018381101561392857fe5b8091505b5092915050565b61393d8282614618565b613946826147d8565b61394f8261483c565b6139588261488f565b613961826148a9565b5050565b600254604080517fa731c4ec000000000000000000000000000000000000000000000000000000008152600160a060020a038581166004830152602482018590529151919092169163a731c4ec91604480830192600092919082900301818387803b1580156139d357600080fd5b505af11580156139e7573d6000803e3d6000fd5b505060008054604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152336004820152602481018790529051600160a060020a03909216945063a9059cbb93506044808201936020939283900390910190829087803b158015612d2357600080fd5b600160009054906101000a9004600160a060020a0316600160a060020a03166354cb50816040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015613aac57600080fd5b505af1158015613ac0573d6000803e3d6000fd5b505050506040513d6020811015613ad657600080fd5b5051811015613ae4576127c3565b613aec6137a9565b1515613afa57613afa6148c3565b613b02611ace565b15156127c3576127c36149fd565b600154604080517f3eaaf86b0000000000000000000000000000000000000000000000000000000081529051600092600160a060020a031691633eaaf86b91600480830192602092919082900301818787803b158015613b6f57600080fd5b505af1158015613b83573d6000803e3d6000fd5b505050506040513d6020811015613b9957600080fd5b505115613ba557600080fd5b60008054604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051600160a060020a03909216926370a08231926024808401936020939083900390910190829087803b158015613c0c57600080fd5b505af1158015613c20573d6000803e3d6000fd5b505050506040513d6020811015613c3657600080fd5b5051600154604080517ff7ea7a3d000000000000000000000000000000000000000000000000000000008152600481018490529051929350600160a060020a039091169163f7ea7a3d9160248082019260009290919082900301818387803b15801561131357600080fd5b600080613cb583613cb0614af8565b614d16565b90506121f0600160009054906101000a9004600160a060020a0316600160a060020a03166301f0e6ad6040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015613d0d57600080fd5b505af1158015613d21573d6000803e3d6000fd5b505050506040513d6020811015613d3757600080fd5b5051613cb083614d2e565b600080600080600080600260009054906101000a9004600160a060020a0316600160a060020a0316631e2273a7896040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b158015613da957600080fd5b505af1158015613dbd573d6000803e3d6000fd5b505050506040513d6020811015613dd357600080fd5b50519450613ddf614af8565b9350613e06613dee8686614d16565b613cb089613dfe57600019613e01565b60015b614d41565b9250613e93600160009054906101000a9004600160a060020a0316600160a060020a03166301f0e6ad6040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015613e5e57600080fd5b505af1158015613e72573d6000803e3d6000fd5b505050506040513d6020811015613e8857600080fd5b5051613cb085614d2e565b9150613e9f8583614d16565b600254604080517fd8fcfd6b000000000000000000000000000000000000000000000000000000008152600f84810b900b60048201529051929350600160a060020a039091169163d8fcfd6b916024808201926020929091908290030181600087803b158015613f0e57600080fd5b505af1158015613f22573d6000803e3d6000fd5b505050506040513d6020811015613f3857600080fd5b505198975050505050505050565b6000806000806000806000806000600260009054906101000a9004600160a060020a0316600160a060020a0316631e2273a78c6040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b158015613fb257600080fd5b505af1158015613fc6573d6000803e3d6000fd5b505050506040513d6020811015613fdc57600080fd5b5051600154604080517f01f0e6ad0000000000000000000000000000000000000000000000000000000081529051929a50614075928b92600160a060020a0316916301f0e6ad9160048083019260209291908290030181600087803b15801561404457600080fd5b505af1158015614058573d6000803e3d6000fd5b505050506040513d602081101561406e57600080fd5b5051614d52565b965061407f614af8565b95506140948761408f6064614d41565b614d52565b9450600093505b606484101561413a576140ae8587614d16565b92506140cc6140c784613cb08d613dfe57600019613e01565b614d2e565b91506140fb876140e56140df8689614d16565b85614d16565b0161408f84866140f56001614d41565b01614d16565b90506141106001670de0b6b3a7640000614d79565b600f0b61411e828703614d90565b600f0b121561412c5761413a565b93506001909201918361409b565b600254604080517fd8fcfd6b000000000000000000000000000000000000000000000000000000008152600f88810b900b60048201529051600160a060020a039092169163d8fcfd6b916024808201926020929091908290030181600087803b1580156141a657600080fd5b505af11580156141ba573d6000803e3d6000fd5b505050506040513d60208110156141d057600080fd5b50519b9a5050505050505050505050565b600080600080600080600260009054906101000a9004600160a060020a0316600160a060020a0316631e2273a7896040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b15801561424857600080fd5b505af115801561425c573d6000803e3d6000fd5b505050506040513d602081101561427257600080fd5b5051945061428687613dfe57600019613e01565b935061429a6142958686614d16565b613ca1565b925061432a600160009054906101000a9004600160a060020a0316600160a060020a03166301f0e6ad6040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156142f257600080fd5b505af1158015614306573d6000803e3d6000fd5b505050506040513d602081101561431c57600080fd5b5051840361408f6002614d41565b91506143368583614d16565b90508615156143525761434f81613cb0605f6064614d79565b90505b600254600160a060020a0316631500214e8163d8fcfd6b6143738589614d16565b6040518263ffffffff1660e060020a0281526004018082600f0b600f0b8152602001915050602060405180830381600087803b1580156143b257600080fd5b505af11580156143c6573d6000803e3d6000fd5b505050506040513d60208110156143dc57600080fd5b5051600254604080517f90cc55640000000000000000000000000000000000000000000000000000000081529051600160a060020a03909216916390cc5564916004808201926020929091908290030181600087803b15801561443e57600080fd5b505af1158015614452573d6000803e3d6000fd5b505050506040513d602081101561446857600080fd5b50516040805160e060020a63ffffffff8616028152600481019390935260248301919091525160448083019260209291908290030181600087803b158015613f0e57600080fd5b60008082848115156144bd57fe5b04949350505050565b60008183106144d557826121f0565b50919050565b60008183106144ea57816121f0565b5090919050565b600080831515614504576000915061392c565b5082820282848281151561451457fe5b041461392857fe5b600254604080517f7442f427000000000000000000000000000000000000000000000000000000008152600160a060020a0385811660048301526024820185905291519190921691637442f42791604480830192600092919082900301818387803b15801561458a57600080fd5b505af115801561459e573d6000803e3d6000fd5b505060008054604080517f23b872dd000000000000000000000000000000000000000000000000000000008152600160a060020a0388811660048301523060248301526044820188905291519190921694506323b872dd935060648083019360209383900390910190829087803b158015612d2357600080fd5b60008061462484614daf565b915061462f84614e8a565b9050600160a060020a038316156146c857600254604080517f92093e7d000000000000000000000000000000000000000000000000000000008152600160a060020a038681166004830152915191909216916392093e7d91859160248082019260009290919082900301818588803b1580156146aa57600080fd5b505af11580156146be573d6000803e3d6000fd5b50505050506146d5565b6146d28183613919565b90505b6146dd61183f565b151561476657600154604080517f7802cbaf000000000000000000000000000000000000000000000000000000008152600481018490529051600160a060020a0390921691637802cbaf9160248082019260009290919082900301818387803b15801561474957600080fd5b505af115801561475d573d6000803e3d6000fd5b50505050612d4d565b600260009054906101000a9004600160a060020a0316600160a060020a0316630f900587826040518263ffffffff1660e060020a0281526004016000604051808303818588803b1580156147b957600080fd5b505af11580156147cd573d6000803e3d6000fd5b505050505050505050565b600254600160a060020a031663a64b0b626147f283614ef4565b6040518263ffffffff1660e060020a0281526004016000604051808303818588803b15801561482057600080fd5b505af1158015614834573d6000803e3d6000fd5b505050505050565b600154600160a060020a0316637802cbaf61485683614f5e565b6040518263ffffffff1660e060020a02815260040180828152602001915050600060405180830381600087803b15801561131357600080fd5b600254600160a060020a031663195d06ff6147f283614fc8565b600254600160a060020a03166387451d526147f283615032565b600254604080517f312220bc0000000000000000000000000000000000000000000000000000000081523360048201529051600160a060020a039092169163312220bc9160248082019260009290919082900301818387803b15801561492857600080fd5b505af115801561493c573d6000803e3d6000fd5b5050505033600160a060020a03167f69877c564f0b5f9e9cd1329a8b1198067735170a423215c8b247b8f6d39b4b7f600160009054906101000a9004600160a060020a0316600160a060020a031663ca2c139c6040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156149be57600080fd5b505af11580156149d2573d6000803e3d6000fd5b505050506040513d60208110156149e857600080fd5b505160408051918252519081900360200190a2565b600254604080517f2ab6a50e0000000000000000000000000000000000000000000000000000000081523360048201529051600160a060020a0390921691632ab6a50e9160248082019260009290919082900301818387803b158015614a6257600080fd5b505af1158015614a76573d6000803e3d6000fd5b5050505033600160a060020a03167f60ee109d675dd732dee88b27c9222abb71bd53a54735a639ba070041d534d730600160009054906101000a9004600160a060020a0316600160a060020a031663cc4515816040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156149be57600080fd5b6000614b81600160009054906101000a9004600160a060020a0316600160a060020a031663709d94466040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015614b5057600080fd5b505af1158015614b64573d6000803e3d6000fd5b505050506040513d6020811015614b7a57600080fd5b505161509c565b1515614b8c57600080fd5b600154604080517fd5562acd0000000000000000000000000000000000000000000000000000000081529051614bed92600160a060020a03169163d5562acd9160048083019260209291908290030181600087803b158015614b5057600080fd5b1515614bf857600080fd5b610ffe614c84600160009054906101000a9004600160a060020a0316600160a060020a031663709d94466040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015614c5157600080fd5b505af1158015614c65573d6000803e3d6000fd5b505050506040513d6020811015614c7b57600080fd5b50516064614d79565b600154604080517fd5562acd000000000000000000000000000000000000000000000000000000008152905161408f92600160a060020a03169163d5562acd9160048083019260209291908290030181600087803b158015614ce557600080fd5b505af1158015614cf9573d6000803e3d6000fd5b505050506040513d6020811015614d0f57600080fd5b5051614d41565b68010000000000000000600f92830b9190920b020590565b6000614d3b8260646150d9565b92915050565b60070b680100000000000000000290565b6000600f82810b9084900b6801000000000000000002811515614d7157fe5b059392505050565b60006121f0614d8784614d41565b61408f84614d41565b60008082600f0b1315614da4575080611da6565b816000039050611da6565b600254604080517f111081f80000000000000000000000000000000000000000000000000000000081529051600092600160a060020a031691631500214e918591849163111081f89160048082019260209290919082900301818a87803b158015614e1957600080fd5b505af1158015614e2d573d6000803e3d6000fd5b505050506040513d6020811015614e4357600080fd5b50516040805160e060020a63ffffffff8616028152600481019390935260248301919091525160448083019260209291908290030181600087803b158015612ffe57600080fd5b600254604080517f1bde12480000000000000000000000000000000000000000000000000000000081529051600092600160a060020a031691631500214e9185918491631bde12489160048082019260209290919082900301818a87803b158015614e1957600080fd5b600254604080517f584451f20000000000000000000000000000000000000000000000000000000081529051600092600160a060020a031691631500214e918591849163584451f29160048082019260209290919082900301818a87803b158015614e1957600080fd5b600254604080517f44c403670000000000000000000000000000000000000000000000000000000081529051600092600160a060020a031691631500214e91859184916344c403679160048082019260209290919082900301818a87803b158015614e1957600080fd5b600254604080517fa37fdf7f0000000000000000000000000000000000000000000000000000000081529051600092600160a060020a031691631500214e918591849163a37fdf7f9160048082019260209290919082900301818a87803b158015614e1957600080fd5b600254604080517f69ae4de00000000000000000000000000000000000000000000000000000000081529051600092600160a060020a031691631500214e91859184916369ae4de09160048082019260209290919082900301818a87803b158015614e1957600080fd5b6000808267ffffffffffffffff1610158015614d3b57506150bb615130565b67ffffffffffffffff168267ffffffffffffffff1611159050919050565b60008068010000000000000000815b848160070b1215615126579181019161510b82613cb08861408f60018601614d41565b915081600f0b6000141561511e57615126565b6001016150e8565b5090949350505050565b67800000000000000019905600a165627a7a723058208c6bd04c9397cad102e05dd067feb84489020adb3cd959de252f32be39af9d7a0029000000000000000000000000fef773765183659ee271b033c2553afd1f15c5a5

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000fef773765183659ee271b033c2553afd1f15c5a5

-----Decoded View---------------
Arg [0] : dataContractAddress (address): 0xfeF773765183659EE271B033C2553afD1F15c5a5

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000fef773765183659ee271b033c2553afd1f15c5a5


Swarm Source

bzzr://8c6bd04c9397cad102e05dd067feb84489020adb3cd959de252f32be39af9d7a
Block Transaction Difficulty Gas Used Reward
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.