ETH Price: $2,128.73 (+7.32%)
Gas: 0.1 Gwei
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Add Oracles73105182019-03-05 17:02:022556 days ago1551805322IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.0009200820
Add Users73101342019-03-05 15:41:072556 days ago1551800467IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.0022535620
Add Users72155762019-02-13 14:46:252576 days ago1550069185IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.00030956.6
Issue Hardcap To...71506652019-01-30 21:32:072590 days ago1548883927IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.000636773.3
Issue Hardcap To...70954652019-01-19 23:55:052600 days ago1547942105IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.000686313.3
Add Users70954562019-01-19 23:53:032600 days ago1547941983IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.000154963.3
Issue Hardcap To...70422212019-01-10 11:43:142610 days ago1547120594IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.000686313.3
Add Users70422142019-01-10 11:41:582610 days ago1547120518IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.000317996.771875
Issue Hardcap To...69291352018-12-21 22:57:222629 days ago1545433042IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.000837473.3
Add Users69291332018-12-21 22:56:312630 days ago1545432991IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.000108472.31
Issue Hardcap To...69215362018-12-20 15:49:032631 days ago1545320943IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.001143855.5
Add Users69215262018-12-20 15:46:312631 days ago1545320791IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.000258265.5
Issue Hardcap To...69081562018-12-18 8:58:202633 days ago1545123500IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.001496167.194
Add Users69081482018-12-18 8:55:332633 days ago1545123333IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.000361577.7
Issue Hardcap To...68643492018-12-11 2:17:142640 days ago1544494634IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.00091484.4
Issue Hardcap To...68430982018-12-07 14:28:092644 days ago1544192889IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.001698638.8
Issue Hardcap To...68429232018-12-07 13:47:302644 days ago1544190450IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.001061645.5
Issue Hardcap To...68326112018-12-05 20:38:382646 days ago1544042318IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.001730786.82
Add Users68325652018-12-05 20:27:472646 days ago1544041667IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.000258265.5
Issue Hardcap To...67990902018-11-30 7:38:232651 days ago1543563503IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.0022877111
Add Users67990462018-11-30 7:27:342651 days ago1543562854IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.0005681912.1
Issue Hardcap To...67885112018-11-28 13:49:472653 days ago1543412987IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.001697518.8
Issue Hardcap To...67860772018-11-28 4:07:082653 days ago1543378028IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.001060945.5
Issue Hardcap To...67651212018-11-24 17:17:262657 days ago1543079846IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.001060945.5
Issue Hardcap To...67570092018-11-23 9:30:282658 days ago1542965428IN
0x1E0c47Eb...8a2EF58Df
0 ETH0.002511799.9
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
EmissionProvider

Compiler Version
v0.4.19+commit.c4cbbb05

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
/**
 *Submitted for verification at Etherscan.io on 2018-10-01
*/

pragma solidity ^0.4.11;

/**
 * @title Owned contract with safe ownership pass.
 *
 * Note: all the non constant functions return false instead of throwing in case if state change
 * didn't happen yet.
 */
contract Owned {
    /**
     * Contract owner address
     */
    address public contractOwner;

    /**
     * Contract owner address
     */
    address public pendingContractOwner;

    function Owned() {
        contractOwner = msg.sender;
    }

    /**
    * @dev Owner check modifier
    */
    modifier onlyContractOwner() {
        if (contractOwner == msg.sender) {
            _;
        }
    }

    /**
     * @dev Destroy contract and scrub a data
     * @notice Only owner can call it
     */
    function destroy() onlyContractOwner {
        suicide(msg.sender);
    }

    /**
     * Prepares ownership pass.
     *
     * Can only be called by current owner.
     *
     * @param _to address of the next owner. 0x0 is not allowed.
     *
     * @return success.
     */
    function changeContractOwnership(address _to) onlyContractOwner() returns(bool) {
        if (_to  == 0x0) {
            return false;
        }

        pendingContractOwner = _to;
        return true;
    }

    /**
     * Finalize ownership pass.
     *
     * Can only be called by pending owner.
     *
     * @return success.
     */
    function claimContractOwnership() returns(bool) {
        if (pendingContractOwner != msg.sender) {
            return false;
        }

        contractOwner = pendingContractOwner;
        delete pendingContractOwner;

        return true;
    }
}

contract ERC20Interface {
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed from, address indexed spender, uint256 value);
    string public symbol;

    function totalSupply() constant returns (uint256 supply);
    function balanceOf(address _owner) constant returns (uint256 balance);
    function transfer(address _to, uint256 _value) returns (bool success);
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
    function approve(address _spender, uint256 _value) returns (bool success);
    function allowance(address _owner, address _spender) constant returns (uint256 remaining);
}

/**
 * @title Generic owned destroyable contract
 */
contract Object is Owned {
    /**
    *  Common result code. Means everything is fine.
    */
    uint constant OK = 1;
    uint constant OWNED_ACCESS_DENIED_ONLY_CONTRACT_OWNER = 8;

    function withdrawnTokens(address[] tokens, address _to) onlyContractOwner returns(uint) {
        for(uint i=0;i<tokens.length;i++) {
            address token = tokens[i];
            uint balance = ERC20Interface(token).balanceOf(this);
            if(balance != 0)
                ERC20Interface(token).transfer(_to,balance);
        }
        return OK;
    }

    function checkOnlyContractOwner() internal constant returns(uint) {
        if (contractOwner == msg.sender) {
            return OK;
        }

        return OWNED_ACCESS_DENIED_ONLY_CONTRACT_OWNER;
    }
}

/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a * b;
        assert(a == 0 || c / a == b);
        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // 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;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        assert(b <= a);
        return a - b;
    }

    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        assert(c >= a);
        return c;
    }
}

contract OracleContractAdapter is Object {

    event OracleAdded(address _oracle);
    event OracleRemoved(address _oracle);

    mapping(address => bool) public oracles;

    /// @dev Allow access only for oracle
    modifier onlyOracle {
        if (oracles[msg.sender]) {
            _;
        }
    }

    modifier onlyOracleOrOwner {
        if (oracles[msg.sender] || msg.sender == contractOwner) {
            _;
        }
    }

    /// @notice Add oracles to whitelist.
    ///
    /// @param _whitelist user list.
    function addOracles(address[] _whitelist) 
    onlyContractOwner 
    external 
    returns (uint) 
    {
        for (uint _idx = 0; _idx < _whitelist.length; ++_idx) {
            address _oracle = _whitelist[_idx];
            if (_oracle != 0x0 && !oracles[_oracle]) {
                oracles[_oracle] = true;
                _emitOracleAdded(_oracle);
            }
        }
        return OK;
    }

    /// @notice Removes oracles from whitelist.
    ///
    /// @param _blacklist user in whitelist.
    function removeOracles(address[] _blacklist) 
    onlyContractOwner 
    external 
    returns (uint) 
    {
        for (uint _idx = 0; _idx < _blacklist.length; ++_idx) {
            address _oracle = _blacklist[_idx];
            if (_oracle != 0x0 && oracles[_oracle]) {
                delete oracles[_oracle];
                _emitOracleRemoved(_oracle);
            }
        }
        return OK;
    }

    function _emitOracleAdded(address _oracle) internal {
        OracleAdded(_oracle);
    }

    function _emitOracleRemoved(address _oracle) internal {
        OracleRemoved(_oracle);
    }
}

/// @title ServiceAllowance.
///
/// Provides a way to delegate operation allowance decision to a service contract
contract ServiceAllowance {
    function isTransferAllowed(address _from, address _to, address _sender, address _token, uint _value) public view returns (bool);
}

/// @title DepositWalletInterface
///
/// Defines an interface for a wallet that can be deposited/withdrawn by 3rd contract
contract DepositWalletInterface {
    function deposit(address _asset, address _from, uint256 amount) public returns (uint);
    function withdraw(address _asset, address _to, uint256 amount) public returns (uint);
}

contract ProfiteroleEmitter {

    event DepositPendingAdded(uint amount, address from, uint timestamp);
    event BonusesWithdrawn(bytes32 userKey, uint amount, uint timestamp);

    event Error(uint errorCode);

    function _emitError(uint _errorCode) internal returns (uint) {
        Error(_errorCode);
        return _errorCode;
    }
}

contract TreasuryEmitter {
    event TreasuryDeposited(bytes32 userKey, uint value, uint lockupDate);
    event TreasuryWithdrawn(bytes32 userKey, uint value);
}

contract ERC20 {
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed from, address indexed spender, uint256 value);
    string public symbol;

    function totalSupply() constant returns (uint256 supply);
    function balanceOf(address _owner) constant returns (uint256 balance);
    function transfer(address _to, uint256 _value) returns (bool success);
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
    function approve(address _spender, uint256 _value) returns (bool success);
    function allowance(address _owner, address _spender) constant returns (uint256 remaining);
}




/// @title Treasury contract.
///
/// Treasury for CCs deposits for particular fund with bmc-days calculations.
/// Accept BMC deposits from Continuous Contributors via oracle and
/// calculates bmc-days metric for each CC's role.
contract Treasury is OracleContractAdapter, ServiceAllowance, TreasuryEmitter {

    /* ERROR CODES */

    uint constant PERCENT_PRECISION = 10000;

    uint constant TREASURY_ERROR_SCOPE = 108000;
    uint constant TREASURY_ERROR_TOKEN_NOT_SET_ALLOWANCE = TREASURY_ERROR_SCOPE + 1;

    using SafeMath for uint;

    struct LockedDeposits {
        uint counter;
        mapping(uint => uint) index2Date;
        mapping(uint => uint) date2deposit;
    }

    struct Period {
        uint transfersCount;
        uint totalBmcDays;
        uint bmcDaysPerDay;
        uint startDate;
        mapping(bytes32 => uint) user2bmcDays;
        mapping(bytes32 => uint) user2lastTransferIdx;
        mapping(bytes32 => uint) user2balance;
        mapping(uint => uint) transfer2date;
    }

    /* FIELDS */

    address token;
    address profiterole;
    uint periodsCount;

    mapping(uint => Period) periods;
    mapping(uint => uint) periodDate2periodIdx;
    mapping(bytes32 => uint) user2lastPeriodParticipated;
    mapping(bytes32 => LockedDeposits) user2lockedDeposits;

    /* MODIFIERS */

    /// @dev Only profiterole contract allowed to invoke guarded functions
    modifier onlyProfiterole {
        require(profiterole == msg.sender);
        _;
    }

    /* PUBLIC */
    
    function Treasury(address _token) public {
        require(address(_token) != 0x0);
        token = _token;
        periodsCount = 1;
    }

    function init(address _profiterole) public onlyContractOwner returns (uint) {
        require(_profiterole != 0x0);
        profiterole = _profiterole;
        return OK;
    }

    /// @notice Do not accept Ether transfers
    function() payable public {
        revert();
    }

    /* EXTERNAL */

    /// @notice Deposits tokens on behalf of users
    /// Allowed only for oracle.
    ///
    /// @param _userKey aggregated user key (user ID + role ID)
    /// @param _value amount of tokens to deposit
    /// @param _feeAmount amount of tokens that will be taken from _value as fee
    /// @param _feeAddress destination address for fee transfer
    /// @param _lockupDate lock up date for deposit. Until that date the deposited value couldn't be withdrawn
    ///
    /// @return result code of an operation
    function deposit(bytes32 _userKey, uint _value, uint _feeAmount, address _feeAddress, uint _lockupDate) external onlyOracle returns (uint) {
        require(_userKey != bytes32(0));
        require(_value != 0);
        require(_feeAmount < _value);

        ERC20 _token = ERC20(token);
        if (_token.allowance(msg.sender, address(this)) < _value) {
            return TREASURY_ERROR_TOKEN_NOT_SET_ALLOWANCE;
        }

        uint _depositedAmount = _value - _feeAmount;
        _makeDepositForPeriod(_userKey, _depositedAmount, _lockupDate);

        uint _periodsCount = periodsCount;
        user2lastPeriodParticipated[_userKey] = _periodsCount;
        delete periods[_periodsCount].startDate;

        if (!_token.transferFrom(msg.sender, address(this), _value)) {
            revert();
        }

        if (!(_feeAddress == 0x0 || _feeAmount == 0 || _token.transfer(_feeAddress, _feeAmount))) {
            revert();
        }

        TreasuryDeposited(_userKey, _depositedAmount, _lockupDate);
        return OK;
    }

    /// @notice Withdraws deposited tokens on behalf of users
    /// Allowed only for oracle
    ///
    /// @param _userKey aggregated user key (user ID + role ID)
    /// @param _value an amount of tokens that is requrested to withdraw
    /// @param _withdrawAddress address to withdraw; should not be 0x0
    /// @param _feeAmount amount of tokens that will be taken from _value as fee
    /// @param _feeAddress destination address for fee transfer
    ///
    /// @return result of an operation
    function withdraw(bytes32 _userKey, uint _value, address _withdrawAddress, uint _feeAmount, address _feeAddress) external onlyOracle returns (uint) {
        require(_userKey != bytes32(0));
        require(_value != 0);
        require(_feeAmount < _value);

        _makeWithdrawForPeriod(_userKey, _value);
        uint _periodsCount = periodsCount;
        user2lastPeriodParticipated[_userKey] = periodsCount;
        delete periods[_periodsCount].startDate;

        ERC20 _token = ERC20(token);
        if (!(_feeAddress == 0x0 || _feeAmount == 0 || _token.transfer(_feeAddress, _feeAmount))) {
            revert();
        }

        uint _withdrawnAmount = _value - _feeAmount;
        if (!_token.transfer(_withdrawAddress, _withdrawnAmount)) {
            revert();
        }

        TreasuryWithdrawn(_userKey, _withdrawnAmount);
        return OK;
    }

    /// @notice Gets shares (in percents) the user has on provided date
    ///
    /// @param _userKey aggregated user key (user ID + role ID)
    /// @param _date date where period ends
    ///
    /// @return percent from total amount of bmc-days the treasury has on this date.
    /// Use PERCENT_PRECISION to get right precision
    function getSharesPercentForPeriod(bytes32 _userKey, uint _date) public view returns (uint) {
        uint _periodIdx = periodDate2periodIdx[_date];
        if (_date != 0 && _periodIdx == 0) {
            return 0;
        }

        if (_date == 0) {
            _date = now;
            _periodIdx = periodsCount;
        }

        uint _bmcDays = _getBmcDaysAmountForUser(_userKey, _date, _periodIdx);
        uint _totalBmcDeposit = _getTotalBmcDaysAmount(_date, _periodIdx);
        return _totalBmcDeposit != 0 ? _bmcDays * PERCENT_PRECISION / _totalBmcDeposit : 0;
    }

    /// @notice Gets user balance that is deposited
    /// @param _userKey aggregated user key (user ID + role ID)
    /// @return an amount of tokens deposited on behalf of user
    function getUserBalance(bytes32 _userKey) public view returns (uint) {
        uint _lastPeriodForUser = user2lastPeriodParticipated[_userKey];
        if (_lastPeriodForUser == 0) {
            return 0;
        }

        if (_lastPeriodForUser <= periodsCount.sub(1)) {
            return periods[_lastPeriodForUser].user2balance[_userKey];
        }

        return periods[periodsCount].user2balance[_userKey];
    }

    /// @notice Gets amount of locked deposits for user
    /// @param _userKey aggregated user key (user ID + role ID)
    /// @return an amount of tokens locked
    function getLockedUserBalance(bytes32 _userKey) public returns (uint) {
        return _syncLockedDepositsAmount(_userKey);
    }

    /// @notice Gets list of locked up deposits with dates when they will be available to withdraw
    /// @param _userKey aggregated user key (user ID + role ID)
    /// @return {
    ///     "_lockupDates": "list of lockup dates of deposits",
    ///     "_deposits": "list of deposits"
    /// }
    function getLockedUserDeposits(bytes32 _userKey) public view returns (uint[] _lockupDates, uint[] _deposits) {
        LockedDeposits storage _lockedDeposits = user2lockedDeposits[_userKey];
        uint _lockedDepositsCounter = _lockedDeposits.counter;
        _lockupDates = new uint[](_lockedDepositsCounter);
        _deposits = new uint[](_lockedDepositsCounter);

        uint _pointer = 0;
        for (uint _idx = 1; _idx < _lockedDepositsCounter; ++_idx) {
            uint _lockDate = _lockedDeposits.index2Date[_idx];

            if (_lockDate > now) {
                _lockupDates[_pointer] = _lockDate;
                _deposits[_pointer] = _lockedDeposits.date2deposit[_lockDate];
                ++_pointer;
            }
        }
    }

    /// @notice Gets total amount of bmc-day accumulated due provided date
    /// @param _date date where period ends
    /// @return an amount of bmc-days
    function getTotalBmcDaysAmount(uint _date) public view returns (uint) {
        return _getTotalBmcDaysAmount(_date, periodsCount);
    }

    /// @notice Makes a checkpoint to start counting a new period
    /// @dev Should be used only by Profiterole contract
    function addDistributionPeriod() public onlyProfiterole returns (uint) {
        uint _periodsCount = periodsCount;
        uint _nextPeriod = _periodsCount.add(1);
        periodDate2periodIdx[now] = _periodsCount;

        Period storage _previousPeriod = periods[_periodsCount];
        uint _totalBmcDeposit = _getTotalBmcDaysAmount(now, _periodsCount);
        periods[_nextPeriod].startDate = now;
        periods[_nextPeriod].bmcDaysPerDay = _previousPeriod.bmcDaysPerDay;
        periods[_nextPeriod].totalBmcDays = _totalBmcDeposit;
        periodsCount = _nextPeriod;

        return OK;
    }

    function isTransferAllowed(address, address, address, address, uint) public view returns (bool) {
        return true;
    }

    /* INTERNAL */

    function _makeDepositForPeriod(bytes32 _userKey, uint _value, uint _lockupDate) internal {
        Period storage _transferPeriod = periods[periodsCount];

        _transferPeriod.user2bmcDays[_userKey] = _getBmcDaysAmountForUser(_userKey, now, periodsCount);
        _transferPeriod.totalBmcDays = _getTotalBmcDaysAmount(now, periodsCount);
        _transferPeriod.bmcDaysPerDay = _transferPeriod.bmcDaysPerDay.add(_value);

        uint _userBalance = getUserBalance(_userKey);
        uint _updatedTransfersCount = _transferPeriod.transfersCount.add(1);
        _transferPeriod.transfersCount = _updatedTransfersCount;
        _transferPeriod.transfer2date[_transferPeriod.transfersCount] = now;
        _transferPeriod.user2balance[_userKey] = _userBalance.add(_value);
        _transferPeriod.user2lastTransferIdx[_userKey] = _updatedTransfersCount;

        _registerLockedDeposits(_userKey, _value, _lockupDate);
    }

    function _makeWithdrawForPeriod(bytes32 _userKey, uint _value) internal {
        uint _userBalance = getUserBalance(_userKey);
        uint _lockedBalance = _syncLockedDepositsAmount(_userKey);
        require(_userBalance.sub(_lockedBalance) >= _value);

        uint _periodsCount = periodsCount;
        Period storage _transferPeriod = periods[_periodsCount];

        _transferPeriod.user2bmcDays[_userKey] = _getBmcDaysAmountForUser(_userKey, now, _periodsCount);
        uint _totalBmcDeposit = _getTotalBmcDaysAmount(now, _periodsCount);
        _transferPeriod.totalBmcDays = _totalBmcDeposit;
        _transferPeriod.bmcDaysPerDay = _transferPeriod.bmcDaysPerDay.sub(_value);

        uint _updatedTransferCount = _transferPeriod.transfersCount.add(1);
        _transferPeriod.transfer2date[_updatedTransferCount] = now;
        _transferPeriod.user2lastTransferIdx[_userKey] = _updatedTransferCount;
        _transferPeriod.user2balance[_userKey] = _userBalance.sub(_value);
        _transferPeriod.transfersCount = _updatedTransferCount;
    }

    function _registerLockedDeposits(bytes32 _userKey, uint _amount, uint _lockupDate) internal {
        if (_lockupDate <= now) {
            return;
        }

        LockedDeposits storage _lockedDeposits = user2lockedDeposits[_userKey];
        uint _lockedBalance = _lockedDeposits.date2deposit[_lockupDate];

        if (_lockedBalance == 0) {
            uint _lockedDepositsCounter = _lockedDeposits.counter.add(1);
            _lockedDeposits.counter = _lockedDepositsCounter;
            _lockedDeposits.index2Date[_lockedDepositsCounter] = _lockupDate;
        }
        _lockedDeposits.date2deposit[_lockupDate] = _lockedBalance.add(_amount);
    }

    function _syncLockedDepositsAmount(bytes32 _userKey) internal returns (uint _lockedSum) {
        LockedDeposits storage _lockedDeposits = user2lockedDeposits[_userKey];
        uint _lockedDepositsCounter = _lockedDeposits.counter;

        for (uint _idx = 1; _idx <= _lockedDepositsCounter; ++_idx) {
            uint _lockDate = _lockedDeposits.index2Date[_idx];

            if (_lockDate <= now) {
                _lockedDeposits.index2Date[_idx] = _lockedDeposits.index2Date[_lockedDepositsCounter];

                delete _lockedDeposits.index2Date[_lockedDepositsCounter];
                delete _lockedDeposits.date2deposit[_lockDate];

                _lockedDepositsCounter = _lockedDepositsCounter.sub(1);
                continue;
            }

            _lockedSum = _lockedSum.add(_lockedDeposits.date2deposit[_lockDate]);
        }

        _lockedDeposits.counter = _lockedDepositsCounter;
    }

    function _getBmcDaysAmountForUser(bytes32 _userKey, uint _date, uint _periodIdx) internal view returns (uint) {
        uint _lastPeriodForUserIdx = user2lastPeriodParticipated[_userKey];
        if (_lastPeriodForUserIdx == 0) {
            return 0;
        }

        Period storage _transferPeriod = _lastPeriodForUserIdx <= _periodIdx ? periods[_lastPeriodForUserIdx] : periods[_periodIdx];
        uint _lastTransferDate = _transferPeriod.transfer2date[_transferPeriod.user2lastTransferIdx[_userKey]];
        // NOTE: It is an intended substraction separation to correctly round dates
        uint _daysLong = (_date / 1 days) - (_lastTransferDate / 1 days);
        uint _bmcDays = _transferPeriod.user2bmcDays[_userKey];
        return _bmcDays.add(_transferPeriod.user2balance[_userKey] * _daysLong);
    }

    /* PRIVATE */

    function _getTotalBmcDaysAmount(uint _date, uint _periodIdx) private view returns (uint) {
        Period storage _depositPeriod = periods[_periodIdx];
        uint _transfersCount = _depositPeriod.transfersCount;
        uint _lastRecordedDate = _transfersCount != 0 ? _depositPeriod.transfer2date[_transfersCount] : _depositPeriod.startDate;

        if (_lastRecordedDate == 0) {
            return 0;
        }

        // NOTE: It is an intended substraction separation to correctly round dates
        uint _daysLong = (_date / 1 days).sub((_lastRecordedDate / 1 days));
        uint _totalBmcDeposit = _depositPeriod.totalBmcDays.add(_depositPeriod.bmcDaysPerDay.mul(_daysLong));
        return _totalBmcDeposit;
    }
}

/// @title Profiterole contract
/// Collector and distributor for creation and redemption fees.
/// Accepts bonus tokens from EmissionProvider, BurningMan or other distribution source.
/// Calculates CCs shares in bonuses. Uses Treasury Contract as source of shares in bmc-days.
/// Allows to withdraw bonuses on request.
contract Profiterole is OracleContractAdapter, ServiceAllowance, ProfiteroleEmitter {

    uint constant PERCENT_PRECISION = 10000;

    uint constant PROFITEROLE_ERROR_SCOPE = 102000;
    uint constant PROFITEROLE_ERROR_INSUFFICIENT_DISTRIBUTION_BALANCE = PROFITEROLE_ERROR_SCOPE + 1;
    uint constant PROFITEROLE_ERROR_INSUFFICIENT_BONUS_BALANCE = PROFITEROLE_ERROR_SCOPE + 2;
    uint constant PROFITEROLE_ERROR_TRANSFER_ERROR = PROFITEROLE_ERROR_SCOPE + 3;

    using SafeMath for uint;

    struct Balance {
        uint left;
        bool initialized;
    }

    struct Deposit {
        uint balance;
        uint left;
        uint nextDepositDate;
        mapping(bytes32 => Balance) leftToWithdraw;
    }

    struct UserBalance {
        uint lastWithdrawDate;
    }

    mapping(address => bool) distributionSourcesList;
    mapping(bytes32 => UserBalance) bonusBalances;
    mapping(uint => Deposit) public distributionDeposits;

    uint public firstDepositDate;
    uint public lastDepositDate;

    address public bonusToken;
    address public treasury;
    address public wallet;

    /// @dev Guards functions only for distributionSource invocations
    modifier onlyDistributionSource {
        if (!distributionSourcesList[msg.sender]) {
            revert();
        }
        _;
    }

    function Profiterole(address _bonusToken, address _treasury, address _wallet) public {
        require(_bonusToken != 0x0);
        require(_treasury != 0x0);
        require(_wallet != 0x0);

        bonusToken = _bonusToken;
        treasury = _treasury;
        wallet = _wallet;
    }

    function() payable public {
        revert();
    }

    /* EXTERNAL */

    /// @notice Sets new treasury address
    /// Only for contract owner.
    function updateTreasury(address _treasury) external onlyContractOwner returns (uint) {
        require(_treasury != 0x0);
        treasury = _treasury;
        return OK;
    }

    /// @notice Sets new wallet address for profiterole
    /// Only for contract owner.
    function updateWallet(address _wallet) external onlyContractOwner returns (uint) {
        require(_wallet != 0x0);
        wallet = _wallet;
        return OK;
    }

    /// @notice Add distribution sources to whitelist.
    ///
    /// @param _whitelist addresses list.
    function addDistributionSources(address[] _whitelist) external onlyContractOwner returns (uint) {
        for (uint _idx = 0; _idx < _whitelist.length; ++_idx) {
            distributionSourcesList[_whitelist[_idx]] = true;
        }
        return OK;
    }

    /// @notice Removes distribution sources from whitelist.
    /// Only for contract owner.
    ///
    /// @param _blacklist addresses in whitelist.
    function removeDistributionSources(address[] _blacklist) external onlyContractOwner returns (uint) {
        for (uint _idx = 0; _idx < _blacklist.length; ++_idx) {
            delete distributionSourcesList[_blacklist[_idx]];
        }
        return OK;
    }

    /// @notice Allows to withdraw user's bonuses that he deserves due to Treasury shares for
    /// every distribution period.
    /// Only oracles allowed to invoke this function.
    ///
    /// @param _userKey aggregated user key (user ID + role ID) on behalf of whom bonuses will be withdrawn
    /// @param _value an amount of tokens to withdraw
    /// @param _withdrawAddress destination address of withdrawal (usually user's address)
    /// @param _feeAmount an amount of fee that will be taken from resulted _value
    /// @param _feeAddress destination address of fee transfer
    ///
    /// @return result code of an operation
    function withdrawBonuses(bytes32 _userKey, uint _value, address _withdrawAddress, uint _feeAmount, address _feeAddress) external onlyOracle returns (uint) {
        require(_userKey != bytes32(0));
        require(_value != 0);
        require(_feeAmount < _value);
        require(_withdrawAddress != 0x0);

        DepositWalletInterface _wallet = DepositWalletInterface(wallet);
        ERC20Interface _bonusToken = ERC20Interface(bonusToken);
        if (_bonusToken.balanceOf(_wallet) < _value) {
            return _emitError(PROFITEROLE_ERROR_INSUFFICIENT_BONUS_BALANCE);
        }

        if (OK != _withdrawBonuses(_userKey, _value)) {
            revert();
        }

        if (!(_feeAddress == 0x0 || _feeAmount == 0 || OK == _wallet.withdraw(_bonusToken, _feeAddress, _feeAmount))) {
            revert();
        }

        if (OK != _wallet.withdraw(_bonusToken, _withdrawAddress, _value - _feeAmount)) {
            revert();
        }

        BonusesWithdrawn(_userKey, _value, now);
        return OK;
    }

    /* PUBLIC */

    /// @notice Gets total amount of bonuses user has during all distribution periods
    /// @param _userKey aggregated user key (user ID + role ID)
    /// @return _sum available amount of bonuses to withdraw
    function getTotalBonusesAmountAvailable(bytes32 _userKey) public view returns (uint _sum) {
        uint _startDate = _getCalculationStartDate(_userKey);
        Treasury _treasury = Treasury(treasury);

        for (
            uint _endDate = lastDepositDate;
            _startDate <= _endDate && _startDate != 0;
            _startDate = distributionDeposits[_startDate].nextDepositDate
        ) {
            Deposit storage _pendingDeposit = distributionDeposits[_startDate];
            Balance storage _userBalance = _pendingDeposit.leftToWithdraw[_userKey];

            if (_userBalance.initialized) {
                _sum = _sum.add(_userBalance.left);
            } else {
                uint _sharesPercent = _treasury.getSharesPercentForPeriod(_userKey, _startDate);
                _sum = _sum.add(_pendingDeposit.balance.mul(_sharesPercent).div(PERCENT_PRECISION));
            }
        }
    }

    /// @notice Gets an amount of bonuses user has for concrete distribution date
    /// @param _userKey aggregated user key (user ID + role ID)
    /// @param _distributionDate date of distribution operation
    /// @return available amount of bonuses to withdraw for selected distribution date
    function getBonusesAmountAvailable(bytes32 _userKey, uint _distributionDate) public view returns (uint) {
        Deposit storage _deposit = distributionDeposits[_distributionDate];
        if (_deposit.leftToWithdraw[_userKey].initialized) {
            return _deposit.leftToWithdraw[_userKey].left;
        }

        uint _sharesPercent = Treasury(treasury).getSharesPercentForPeriod(_userKey, _distributionDate);
        return _deposit.balance.mul(_sharesPercent).div(PERCENT_PRECISION);
    }

    /// @notice Gets total amount of deposits that has left after users' bonus withdrawals
    /// @return amount of deposits available for bonus payments
    function getTotalDepositsAmountLeft() public view returns (uint _amount) {
        uint _lastDepositDate = lastDepositDate;
        for (
            uint _startDate = firstDepositDate;
            _startDate <= _lastDepositDate || _startDate != 0;
            _startDate = distributionDeposits[_startDate].nextDepositDate
        ) {
            _amount = _amount.add(distributionDeposits[_startDate].left);
        }
    }

    /// @notice Gets an amount of deposits that has left after users' bonus withdrawals for selected date
    /// @param _distributionDate date of distribution operation
    /// @return amount of deposits available for bonus payments for concrete distribution date
    function getDepositsAmountLeft(uint _distributionDate) public view returns (uint _amount) {
        return distributionDeposits[_distributionDate].left;
    }

    /// @notice Makes checkmark and deposits tokens on profiterole account
    /// to pay them later as bonuses for Treasury shares holders. Timestamp of transaction
    /// counts as the distribution period date.
    /// Only addresses that were added as a distributionSource are allowed to call this function.
    ///
    /// @param _amount an amount of tokens to distribute
    ///
    /// @return result code of an operation.
    /// PROFITEROLE_ERROR_INSUFFICIENT_DISTRIBUTION_BALANCE, PROFITEROLE_ERROR_TRANSFER_ERROR errors
    /// are possible
    function distributeBonuses(uint _amount) public onlyDistributionSource returns (uint) {

        ERC20Interface _bonusToken = ERC20Interface(bonusToken);

        if (_bonusToken.allowance(msg.sender, address(this)) < _amount) {
            return _emitError(PROFITEROLE_ERROR_INSUFFICIENT_DISTRIBUTION_BALANCE);
        }

        if (!_bonusToken.transferFrom(msg.sender, wallet, _amount)) {
            return _emitError(PROFITEROLE_ERROR_TRANSFER_ERROR);
        }

        if (firstDepositDate == 0) {
            firstDepositDate = now;
        }

        uint _lastDepositDate = lastDepositDate;
        if (_lastDepositDate != 0) {
            distributionDeposits[_lastDepositDate].nextDepositDate = now;
        }

        lastDepositDate = now;
        distributionDeposits[now] = Deposit(_amount, _amount, 0);

        Treasury(treasury).addDistributionPeriod();

        DepositPendingAdded(_amount, msg.sender, now);
        return OK;
    }

    function isTransferAllowed(address, address, address, address, uint) public view returns (bool) {
        return false;
    }

    /* PRIVATE */

    function _getCalculationStartDate(bytes32 _userKey) private view returns (uint _startDate) {
        _startDate = bonusBalances[_userKey].lastWithdrawDate;
        return _startDate != 0 ? _startDate : firstDepositDate;
    }

    function _withdrawBonuses(bytes32 _userKey, uint _value) private returns (uint) {
        uint _startDate = _getCalculationStartDate(_userKey);
        uint _lastWithdrawDate = _startDate;
        Treasury _treasury = Treasury(treasury);

        for (
            uint _endDate = lastDepositDate;
            _startDate <= _endDate && _startDate != 0 && _value > 0;
            _startDate = distributionDeposits[_startDate].nextDepositDate
        ) {
            uint _balanceToWithdraw = _withdrawBonusesFromDeposit(_userKey, _startDate, _value, _treasury);
            _value = _value.sub(_balanceToWithdraw);
        }

        if (_lastWithdrawDate != _startDate) {
            bonusBalances[_userKey].lastWithdrawDate = _lastWithdrawDate;
        }

        if (_value > 0) {
            revert();
        }

        return OK;
    }

    function _withdrawBonusesFromDeposit(bytes32 _userKey, uint _periodDate, uint _value, Treasury _treasury) private returns (uint) {
        Deposit storage _pendingDeposit = distributionDeposits[_periodDate];
        Balance storage _userBalance = _pendingDeposit.leftToWithdraw[_userKey];

        uint _balanceToWithdraw;
        if (_userBalance.initialized) {
            _balanceToWithdraw = _userBalance.left;
        } else {
            uint _sharesPercent = _treasury.getSharesPercentForPeriod(_userKey, _periodDate);
            _balanceToWithdraw = _pendingDeposit.balance.mul(_sharesPercent).div(PERCENT_PRECISION);
            _userBalance.initialized = true;
        }

        if (_balanceToWithdraw > _value) {
            _userBalance.left = _balanceToWithdraw - _value;
            _balanceToWithdraw = _value;
        } else {
            delete _userBalance.left;
        }

        _pendingDeposit.left = _pendingDeposit.left.sub(_balanceToWithdraw);
        return _balanceToWithdraw;
    }
}

/// @title EmissionProviderEmitter
///
/// Organizes and provides a set of events specific for EmissionProvider's role
contract EmissionProviderEmitter {

    event Error(uint errorCode);
    event Emission(bytes32 smbl, address to, uint value);
    event HardcapFinishedManually();
    event Destruction();

    function _emitError(uint _errorCode) internal returns (uint) {
        Error(_errorCode);
        return _errorCode;
    }

    function _emitEmission(bytes32 _smbl, address _to, uint _value) internal {
        Emission(_smbl, _to, _value);
    }

    function _emitHardcapFinishedManually() internal {
        HardcapFinishedManually();
    }

    function _emitDestruction() internal {
        Destruction();
    }
}

contract Token is ERC20 {
    
    bytes32 public smbl;
    address public platform;

    function __transferWithReference(address _to, uint _value, string _reference, address _sender) public returns (bool);
    function __transferFromWithReference(address _from, address _to, uint _value, string _reference, address _sender) public returns (bool);
    function __approve(address _spender, uint _value, address _sender) public returns (bool);
    function getLatestVersion() public returns (address);
    function init(address _bmcPlatform, string _symbol, string _name) public;
    function proposeUpgrade(address _newVersion) public;
}

contract Platform {
    mapping(bytes32 => address) public proxies;
    function name(bytes32 _symbol) public view returns (string);
    function setProxy(address _address, bytes32 _symbol) public returns (uint errorCode);
    function isOwner(address _owner, bytes32 _symbol) public view returns (bool);
    function totalSupply(bytes32 _symbol) public view returns (uint);
    function balanceOf(address _holder, bytes32 _symbol) public view returns (uint);
    function allowance(address _from, address _spender, bytes32 _symbol) public view returns (uint);
    function baseUnit(bytes32 _symbol) public view returns (uint8);
    function proxyTransferWithReference(address _to, uint _value, bytes32 _symbol, string _reference, address _sender) public returns (uint errorCode);
    function proxyTransferFromWithReference(address _from, address _to, uint _value, bytes32 _symbol, string _reference, address _sender) public returns (uint errorCode);
    function proxyApprove(address _spender, uint _value, bytes32 _symbol, address _sender) public returns (uint errorCode);
    function issueAsset(bytes32 _symbol, uint _value, string _name, string _description, uint8 _baseUnit, bool _isReissuable) public returns (uint errorCode);
    function reissueAsset(bytes32 _symbol, uint _value) public returns (uint errorCode);
    function revokeAsset(bytes32 _symbol, uint _value) public returns (uint errorCode);
    function isReissuable(bytes32 _symbol) public view returns (bool);
    function changeOwnership(bytes32 _symbol, address _newOwner) public returns (uint errorCode);
}


/// @title EmissionProvider.
///
/// Provides participation registration and token volume issuance called Emission Event.
/// Full functionality of EmissionProvider issuance will be available after adding a smart contract
/// as part-owner of an ATx asset in asset's platform
contract EmissionProvider is OracleContractAdapter, ServiceAllowance, EmissionProviderEmitter {

    uint constant EMISSION_PROVIDER_ERROR_SCOPE = 107000;
    uint constant EMISSION_PROVIDER_ERROR_WRONG_STATE = EMISSION_PROVIDER_ERROR_SCOPE + 1;
    uint constant EMISSION_PROVIDER_ERROR_INSUFFICIENT_BMC = EMISSION_PROVIDER_ERROR_SCOPE + 2;
    uint constant EMISSION_PROVIDER_ERROR_INTERNAL = EMISSION_PROVIDER_ERROR_SCOPE + 3;

    using SafeMath for uint;

    enum State {
        Init, Waiting, Sale, Reached, Destructed
    }

    uint public startDate;
    uint public endDate;

    uint public tokenSoftcapIssued;
    uint public tokenSoftcap;

    uint tokenHardcapIssuedValue;
    uint tokenHardcapValue;

    address public token;
    address public bonusToken;
    address public profiterole;

    mapping(address => bool) public whitelist;

    bool public destructed;
    bool finishedHardcap;
    bool needInitialization;

    /// @dev Deny any access except during sale period (it's time for sale && hardcap haven't reached yet)
    modifier onlySale {
        var (hardcapState, softcapState) = getState();
        if (!(State.Sale == hardcapState || State.Sale == softcapState)) {
            _emitError(EMISSION_PROVIDER_ERROR_WRONG_STATE);
            assembly {
                mstore(0, 107001) // EMISSION_PROVIDER_ERROR_WRONG_STATE
                return (0, 32)
            }
        }
        _;
    }

    /// @dev Deny any access before all sales will be finished
    modifier onlySaleFinished {
        var (hardcapState, softcapState) = getState();
        if (hardcapState < State.Reached || softcapState < State.Reached) {
            _emitError(EMISSION_PROVIDER_ERROR_WRONG_STATE);
            assembly {
                mstore(0, 107001) // EMISSION_PROVIDER_ERROR_WRONG_STATE
                return (0, 32)
            }
        }
        _;
    }
    /// @dev Deny any access before hardcap will be reached
    modifier notHardcapReached {
        var (state,) = getState();
        if (state >= State.Reached) {
            _emitError(EMISSION_PROVIDER_ERROR_WRONG_STATE);
            assembly {
                mstore(0, 107001) // EMISSION_PROVIDER_ERROR_WRONG_STATE
                return (0, 32)
            }
        }
        _;
    }

    /// @dev Deny any access before softcap will be reached
    modifier notSoftcapReached {
        var (, state) = getState();
        if (state >= State.Reached) {
            _emitError(EMISSION_PROVIDER_ERROR_WRONG_STATE);
            assembly {
                mstore(0, 107001) // EMISSION_PROVIDER_ERROR_WRONG_STATE
                return (0, 32)
            }
        }
        _;
    }

    /// @dev Guards from calls to the contract in destructed state
    modifier notDestructed {
        if (destructed) {
            _emitError(EMISSION_PROVIDER_ERROR_WRONG_STATE);
            assembly {
                mstore(0, 107001) // EMISSION_PROVIDER_ERROR_WRONG_STATE
                return (0, 32)
            }
        }
        _;
    }

    /// @dev Deny any access except the contract is not in init state
    modifier onlyInit {
        var (state,) = getState();
        if (state != State.Init) {
            _emitError(EMISSION_PROVIDER_ERROR_WRONG_STATE);
            assembly {
                mstore(0, 107001) // EMISSION_PROVIDER_ERROR_WRONG_STATE
                return (0, 32)
            }
        }
        _;
    }

    /// @dev Allow access only for whitelisted users
    modifier onlyAllowed(address _account) {
        if (whitelist[_account]) {
            _;
        }
    }

    /// @notice Constructor for EmissionProvider.
    ///
    /// @param _token token that will be served by EmissionProvider
    /// @param _bonusToken shares token used for fee distribution
    /// @param _profiterole address of fee destination
    /// @param _startDate start date of emission event
    /// @param _endDate end date of emission event
    /// @param _tokenHardcap max amount of tokens that are allowed to issue. After reaching this number emission will be stopped.
    function EmissionProvider(
        address _token,
        address _bonusToken,
        address _profiterole,
        uint _startDate,
        uint _endDate,
        uint _tokenSoftcap,
        uint _tokenHardcap
    )
    public
    {
        require(_token != 0x0);
        require(_bonusToken != 0x0);

        require(_profiterole != 0x0);

        require(_startDate != 0);
        require(_endDate > _startDate);

        require(_tokenSoftcap != 0);
        require(_tokenHardcap >= _tokenSoftcap);

        require(Profiterole(_profiterole).bonusToken() == _bonusToken);

        token = _token;
        bonusToken = _bonusToken;
        profiterole = _profiterole;
        startDate = _startDate;
        endDate = _endDate;
        tokenSoftcap = _tokenSoftcap;
        tokenHardcapValue = _tokenHardcap - _tokenSoftcap;
        needInitialization = true;
    }

    /// @dev Payable function. Don't accept any Ether
    function() public payable {
        revert();
    }

    /// @notice Initialization
    /// Issue new ATx tokens for Softcap. After contract goes in Sale state
    function init() public onlyContractOwner onlyInit returns (uint) {
        needInitialization = false;
        bytes32 _symbol = Token(token).smbl();
        if (OK != Platform(Token(token).platform()).reissueAsset(_symbol, tokenSoftcap)) {
            revert();
        }
        return OK;
    }

    /// @notice Gets absolute hardcap value which means it will be greater than softcap value.
    /// Actual value will be equal to `tokenSoftcap - tokenHardcap`
    function tokenHardcap() public view returns (uint) {
        return tokenSoftcap + tokenHardcapValue;
    }

    /// @notice Gets absolute issued hardcap volume which means it will be greater than softcap value.
    /// Actual value will be equal to `tokenSoftcap - tokenHardcapIssued`
    function tokenHardcapIssued() public view returns (uint) {
        return tokenSoftcap + tokenHardcapIssuedValue;
    }

    /// @notice Gets current state of Emission Provider. State changes over time or reaching buyback goals.
    /// @return state of a Emission Provider. 'Init', 'Waiting', 'Sale', 'HardcapReached', 'Destructed` values are possible
    function getState() public view returns (State, State) {
        if (needInitialization) {
            return (State.Init, State.Init);
        }

        if (destructed) {
            return (State.Destructed, State.Destructed);
        }

        if (now < startDate) {
            return (State.Waiting, State.Waiting);
        }

        State _hardcapState = (finishedHardcap || (tokenHardcapIssuedValue == tokenHardcapValue) || (now > endDate))
        ? State.Reached
        : State.Sale;

        State _softcapState = (tokenSoftcapIssued == tokenSoftcap)
        ? State.Reached
        : State.Sale;

        return (_hardcapState, _softcapState);
    }

    /// @notice Add users to whitelist.
    /// @param _whitelist user list.
    function addUsers(address[] _whitelist) public onlyOracleOrOwner onlySale returns (uint) {
        for (uint _idx = 0; _idx < _whitelist.length; ++_idx) {
            whitelist[_whitelist[_idx]] = true;
        }
        return OK;
    }

    /// @notice Removes users from whitelist.
    /// @param _blacklist user in whitelist.
    function removeUsers(address[] _blacklist) public onlyOracleOrOwner onlySale returns (uint) {
        for (uint _idx = 0; _idx < _blacklist.length; ++_idx) {
            delete whitelist[_blacklist[_idx]];
        }
        return OK;
    }

    /// @notice Issue tokens for user.
    /// Access allowed only for oracle while the sale period is active.
    ///
    /// @param _token address for token.
    /// @param _for user address.
    /// @param _value token amount,
    function issueHardcapToken(
        address _token, 
        address _for, 
        uint _value
    ) 
    onlyOracle 
    onlyAllowed(_for) 
    onlySale 
    notHardcapReached 
    public
    returns (uint) 
    {
        require(_token == token);
        require(_value != 0);

        uint _tokenHardcap = tokenHardcapValue;
        uint _issued = tokenHardcapIssuedValue;
        if (_issued.add(_value) > _tokenHardcap) {
            _value = _tokenHardcap.sub(_issued);
        }

        tokenHardcapIssuedValue = _issued.add(_value);

        bytes32 _symbol = Token(_token).smbl();
        if (OK != Platform(Token(_token).platform()).reissueAsset(_symbol, _value)) {
            revert();
        }

        if (!Token(_token).transfer(_for, _value)) {
            revert();
        }

        _emitEmission(_symbol, _for, _value);
        return OK;
    }

    /// @notice Issue tokens for user.
    /// Access allowed only for oracle while the sale period is active.
    ///
    /// @param _token address for token.
    /// @param _for user address.
    /// @param _value token amount,
    function issueSoftcapToken(
        address _token, 
        address _for, 
        uint _value
    ) 
    onlyOracle
    onlyAllowed(_for)
    onlySale
    notSoftcapReached
    public
    returns (uint)
    {
        require(_token == token);
        require(_value != 0);

        uint _tokenSoftcap = tokenSoftcap;
        uint _issued = tokenSoftcapIssued;
        if (_issued.add(_value) > _tokenSoftcap) {
            _value = _tokenSoftcap.sub(_issued);
        }

        tokenSoftcapIssued = _issued.add(_value);

        if (!Token(_token).transfer(_for, _value)) {
            revert();
        }

        _emitEmission(Token(_token).smbl(), _for, _value);
        return OK;
    }

    /// @notice Performs finish hardcap manually
    /// Only by contract owner and in sale period
    function finishHardcap() public onlyContractOwner onlySale notHardcapReached returns (uint) {
        finishedHardcap = true;
        _emitHardcapFinishedManually();
        return OK;
    }

    /// @notice Performs distribution of sent BMC tokens and send them to Profiterole address
    /// Only by oracle address and after reaching hardcap conditions
    function distributeBonuses() public onlyOracleOrOwner onlySaleFinished notDestructed returns (uint) {
        ERC20Interface _token = ERC20Interface(bonusToken);
        uint _balance = _token.balanceOf(address(this));

        if (_balance == 0) {
            return _emitError(EMISSION_PROVIDER_ERROR_INSUFFICIENT_BMC);
        }

        Profiterole _profiterole = Profiterole(profiterole);
        if (!_token.approve(address(_profiterole), _balance)) {
            return _emitError(EMISSION_PROVIDER_ERROR_INTERNAL);
        }

        if (OK != _profiterole.distributeBonuses(_balance)) {
            revert();
        }

        return OK;
    }

    /// @notice Activates distruction.
    /// Access allowed only by contract owner after distruction
    function activateDestruction() public onlyContractOwner onlySaleFinished notDestructed returns (uint) {
        destructed = true;
        _emitDestruction();
        return OK;
    }

    /* ServiceAllowance */

    /// @notice Restricts transfers only for:
    /// 1) oracle and only ATx tokens;
    /// 2) from itself to holder
    function isTransferAllowed(address _from, address _to, address, address _token, uint) public view returns (bool) {
        if (_token == token &&
            ((oracles[_from] && _to == address(this)) ||
            (_from == address(this) && whitelist[_to]))
        ) {
            return true;
        }
    }

    function tokenFallback(address _sender, uint, bytes) external {
        require(msg.sender == Token(token).getLatestVersion());
        require(oracles[_sender]);
    }
}

Contract Security Audit

Contract ABI

API
[{"constant":true,"inputs":[],"name":"profiterole","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"startDate","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"destructed","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"finishHardcap","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getState","outputs":[{"name":"","type":"uint8"},{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_whitelist","type":"address[]"}],"name":"addOracles","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_blacklist","type":"address[]"}],"name":"removeUsers","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"tokenHardcap","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"bonusToken","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_blacklist","type":"address[]"}],"name":"removeOracles","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"claimContractOwnership","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"}],"name":"changeContractOwnership","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"pendingContractOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_whitelist","type":"address[]"}],"name":"addUsers","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"destroy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"activateDestruction","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"whitelist","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"oracles","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tokenHardcapIssued","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_sender","type":"address"},{"name":"","type":"uint256"},{"name":"","type":"bytes"}],"name":"tokenFallback","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"endDate","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"","type":"address"},{"name":"_token","type":"address"},{"name":"","type":"uint256"}],"name":"isTransferAllowed","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_for","type":"address"},{"name":"_value","type":"uint256"}],"name":"issueHardcapToken","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"distributeBonuses","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"tokenSoftcapIssued","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"contractOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"tokens","type":"address[]"},{"name":"_to","type":"address"}],"name":"withdrawnTokens","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"tokenSoftcap","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"init","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_for","type":"address"},{"name":"_value","type":"uint256"}],"name":"issueSoftcapToken","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"token","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_token","type":"address"},{"name":"_bonusToken","type":"address"},{"name":"_profiterole","type":"address"},{"name":"_startDate","type":"uint256"},{"name":"_endDate","type":"uint256"},{"name":"_tokenSoftcap","type":"uint256"},{"name":"_tokenHardcap","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"errorCode","type":"uint256"}],"name":"Error","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"smbl","type":"bytes32"},{"indexed":false,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Emission","type":"event"},{"anonymous":false,"inputs":[],"name":"HardcapFinishedManually","type":"event"},{"anonymous":false,"inputs":[],"name":"Destruction","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_oracle","type":"address"}],"name":"OracleAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_oracle","type":"address"}],"name":"OracleRemoved","type":"event"}]

606060405234156200001057600080fd5b60405160e08062001bc08339810160405280805191906020018051919060200180519190602001805191906020018051919060200180519190602001805160008054600160a060020a03191633600160a060020a03908116919091179091559092508816151590506200008257600080fd5b600160a060020a03861615156200009857600080fd5b600160a060020a0385161515620000ae57600080fd5b831515620000bb57600080fd5b838311620000c857600080fd5b811515620000d557600080fd5b81811015620000e357600080fd5b85600160a060020a031685600160a060020a03166341d4a1ab6000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15156200014d57600080fd5b6102c65a03f115156200015f57600080fd5b50505060405180519050600160a060020a03161415156200017f57600080fd5b60098054600160a060020a03988916600160a060020a031991821617909155600a805497891697821697909717909655600b8054959097169490951693909317909455600355600492909255600682905503600855600d805462ff00001916620100001790556119cb80620001f56000396000f3006060604052600436106101715763ffffffff60e060020a600035041663067906b181146101765780630b97bc86146101a55780630bf1c747146101ca5780630c3c92a3146101f15780631865c57d14610204578063205b931e146102505780632be4a9031461026e5780633f242990146102bd57806341d4a1ab146102d057806345644fd6146102e35780634592cd1d14610301578063557f4bc9146103145780635aa77d3c14610333578063700c94741461034657806383197ef01461039557806392c9a9e2146103aa5780639b19251a146103bd578063addd5099146103dc578063bca19900146103fb578063c0ee0b8a1461040e578063c24a0f8b1461043d578063c32ee59114610450578063c661deb414610484578063c875b1fb146104ac578063cb9bdf45146104bf578063ce606ee0146104d2578063d8f9659b146104e5578063d8fed39e1461053f578063e1c7392a14610552578063fbf22dea14610565578063fc0c546a1461058d575b600080fd5b341561018157600080fd5b6101896105a0565b604051600160a060020a03909116815260200160405180910390f35b34156101b057600080fd5b6101b86105af565b60405190815260200160405180910390f35b34156101d557600080fd5b6101dd6105b5565b604051901515815260200160405180910390f35b34156101fc57600080fd5b6101b86105be565b341561020f57600080fd5b610217610679565b6040518083600481111561022757fe5b60ff16815260200182600481111561023b57fe5b60ff1681526020019250505060405180910390f35b341561025b57600080fd5b6101b86004803560248101910135610726565b341561027957600080fd5b6101b860046024813581810190830135806020818102016040519081016040528093929190818152602001838360200280828437509496506107e995505050505050565b34156102c857600080fd5b6101b86108cd565b34156102db57600080fd5b6101896108d7565b34156102ee57600080fd5b6101b860048035602481019101356108e6565b341561030c57600080fd5b6101dd610998565b341561031f57600080fd5b6101dd600160a060020a03600435166109ef565b341561033e57600080fd5b610189610a4e565b341561035157600080fd5b6101b86004602481358181019083013580602081810201604051908101604052809392919081815260200183836020028082843750949650610a5d95505050505050565b34156103a057600080fd5b6103a8610b3d565b005b34156103b557600080fd5b6101b8610b62565b34156103c857600080fd5b6101dd600160a060020a0360043516610bf5565b34156103e757600080fd5b6101dd600160a060020a0360043516610c0a565b341561040657600080fd5b6101b8610c1f565b341561041957600080fd5b6103a860048035600160a060020a0316906024803591604435918201910135610c29565b341561044857600080fd5b6101b8610cd8565b341561045b57600080fd5b6101dd600160a060020a0360043581169060243581169060443581169060643516608435610cde565b341561048f57600080fd5b6101b8600160a060020a0360043581169060243516604435610d83565b34156104b757600080fd5b6101b861108d565b34156104ca57600080fd5b6101b86112d1565b34156104dd57600080fd5b6101896112d7565b34156104f057600080fd5b6101b8600460248135818101908301358060208181020160405190810160405280939291908181526020018383602002808284375094965050509235600160a060020a031692506112e6915050565b341561054a57600080fd5b6101b8611435565b341561055d57600080fd5b6101b861143b565b341561057057600080fd5b6101b8600160a060020a03600435811690602435166044356115d7565b341561059857600080fd5b610189611800565b600b54600160a060020a031681565b60035481565b600d5460ff1681565b6000805433600160a060020a0390811691161415610676576000806105e1610679565b915091508160048111156105f157fe5b6002148061060a575080600481111561060657fe5b6002145b151561062a5761061c6201a1f961180f565b506201a1f960005260206000f35b6000610634610679565b509050600381600481111561064557fe5b106106565761061c6201a1f961180f565b600d805461ff00191661010017905561066d611848565b600193505b5050505b90565b600080600080600d60029054906101000a900460ff16156106a05760008093509350610720565b600d5460ff16156106b75760048093509350610720565b6003544210156106cd5760018093509350610720565b600d54610100900460ff16806106e65750600854600754145b806106f2575060045442115b6106fd576002610700565b60035b915060065460055414610714576002610717565b60035b90508181935093505b50509091565b600080548190819033600160a060020a03908116911614156107e157600091505b838210156107dc5784848381811061075b57fe5b90506020020135600160a060020a0316905080600160a060020a03166000141580156107a05750600160a060020a03811660009081526002602052604090205460ff16155b156107d157600160a060020a0381166000908152600260205260409020805460ff191660011790556107d181611876565b816001019150610747565b600192505b505092915050565b600160a060020a033316600090815260026020526040812054819060ff1680610820575060005433600160a060020a039081169116145b156108c757600080610830610679565b9150915081600481111561084057fe5b60021480610859575080600481111561085557fe5b6002145b151561086b5761061c6201a1f961180f565b600092505b84518310156108c057600c600086858151811061088957fe5b90602001906020020151600160a060020a031681526020810191909152604001600020805460ff1916905560019290920191610870565b6001935050505b50919050565b6008546006540190565b600a54600160a060020a031681565b600080548190819033600160a060020a03908116911614156107e157600091505b838210156107dc5784848381811061091b57fe5b90506020020135600160a060020a0316905080600160a060020a031660001415801561095f5750600160a060020a03811660009081526002602052604090205460ff165b1561098d57600160a060020a0381166000908152600260205260409020805460ff1916905561098d816118b5565b816001019150610907565b60015460009033600160a060020a039081169116146109b957506000610676565b50600180546000805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a0384161790915516815590565b6000805433600160a060020a0390811691161415610a4957600160a060020a0382161515610a1f57506000610a49565b506001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161781555b919050565b600154600160a060020a031681565b600160a060020a033316600090815260026020526040812054819060ff1680610a94575060005433600160a060020a039081169116145b156108c757600080610aa4610679565b91509150816004811115610ab457fe5b60021480610acd5750806004811115610ac957fe5b6002145b1515610adf5761061c6201a1f961180f565b600092505b84518310156108c0576001600c6000878681518110610aff57fe5b90602001906020020151600160a060020a031681526020810191909152604001600020805460ff191691151591909117905560019290920191610ae4565b60005433600160a060020a0390811691161415610b605733600160a060020a0316ff5b565b6000805433600160a060020a039081169116141561067657600080610b85610679565b90925090506003826004811115610b9857fe5b1080610baf57506003816004811115610bad57fe5b105b15610bc05761061c6201a1f961180f565b600d5460ff1615610bd75761061c6201a1f961180f565b600d805460ff19166001179055610bec6118f5565b60019250505090565b600c6020526000908152604090205460ff1681565b60026020526000908152604090205460ff1681565b6007546006540190565b600954600160a060020a0316630e6d1de96000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610c7157600080fd5b6102c65a03f11515610c8257600080fd5b50505060405180519050600160a060020a031633600160a060020a0316141515610cab57600080fd5b600160a060020a03841660009081526002602052604090205460ff161515610cd257600080fd5b50505050565b60045481565b600954600090600160a060020a038481169116148015610d715750600160a060020a03861660009081526002602052604090205460ff168015610d32575030600160a060020a031685600160a060020a0316145b80610d71575030600160a060020a031686600160a060020a0316148015610d715750600160a060020a0385166000908152600c602052604090205460ff165b15610d7a575060015b95945050505050565b600160a060020a03331660009081526002602052604081205481908190819060ff161561108357600160a060020a0386166000908152600c6020526040902054869060ff161561108157600080610dd8610679565b91509150816004811115610de857fe5b60021480610e015750806004811115610dfd57fe5b6002145b1515610e135761061c6201a1f961180f565b6000610e1d610679565b5090506003816004811115610e2e57fe5b10610e3f5761061c6201a1f961180f565b600954600160a060020a038c8116911614610e5957600080fd5b881515610e6557600080fd5b600854600754909750955086610e81878b63ffffffff61192316565b1115610e9a57610e97878763ffffffff61193916565b98505b610eaa868a63ffffffff61192316565b600755600160a060020a038b1663cb4e75bb6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610ef357600080fd5b6102c65a03f11515610f0457600080fd5b5050506040518051955050600160a060020a038b16634bde38c86000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610f5557600080fd5b6102c65a03f11515610f6657600080fd5b50505060405180519050600160a060020a031663e0873c06868b60006040516020015260405160e060020a63ffffffff851602815260048101929092526024820152604401602060405180830381600087803b1515610fc457600080fd5b6102c65a03f11515610fd557600080fd5b50505060405180516001149050610feb57600080fd5b8a600160a060020a031663a9059cbb8b8b60006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b151561104857600080fd5b6102c65a03f1151561105957600080fd5b50505060405180519050151561106e57600080fd5b611079858b8b61194b565b600197505050505b505b5050509392505050565b600160a060020a03331660009081526002602052604081205481908190819060ff16806110c8575060005433600160a060020a039081169116145b15610672576000806110d8610679565b909250905060038260048111156110eb57fe5b10806111025750600381600481111561110057fe5b105b156111135761061c6201a1f961180f565b600d5460ff161561112a5761061c6201a1f961180f565b600a54600160a060020a03169450846370a082313060006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b151561118657600080fd5b6102c65a03f1151561119757600080fd5b50505060405180519450508315156111bc576111b56201a1fa61180f565b95506112c9565b600b54600160a060020a039081169350851663095ea7b3848660006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b151561122157600080fd5b6102c65a03f1151561123257600080fd5b50505060405180519050151561124e576111b56201a1fb61180f565b82600160a060020a0316630d80fcdb8560006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561129d57600080fd5b6102c65a03f115156112ae57600080fd5b505050604051805160011490506112c457600080fd5b600195505b505050505090565b60055481565b600054600160a060020a031681565b6000805481908190819033600160a060020a039081169116141561142c57600092505b85518310156114275785838151811061131e57fe5b90602001906020020151915081600160a060020a03166370a082313060006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b151561138157600080fd5b6102c65a03f1151561139257600080fd5b5050506040518051915050801561141c5781600160a060020a031663a9059cbb868360006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b151561140057600080fd5b6102c65a03f1151561141157600080fd5b505050604051805150505b600190920191611309565b600193505b50505092915050565b60065481565b60008054819033600160a060020a03908116911614156115d357600061145f610679565b509050600081600481111561147057fe5b146114815761061c6201a1f961180f565b600d805462ff000019169055600954600160a060020a031663cb4e75bb6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156114d557600080fd5b6102c65a03f115156114e657600080fd5b5050506040518051600954909350600160a060020a03169050634bde38c86000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561153b57600080fd5b6102c65a03f1151561154c57600080fd5b50505060405180519050600160a060020a031663e0873c068360065460006040516020015260405160e060020a63ffffffff851602815260048101929092526024820152604401602060405180830381600087803b15156115ac57600080fd5b6102c65a03f115156115bd57600080fd5b50505060405180516001149050610bec57600080fd5b5090565b600160a060020a0333166000908152600260205260408120548190819060ff16156117f757600160a060020a0385166000908152600c6020526040902054859060ff16156110835760008061162a610679565b9150915081600481111561163a57fe5b60021480611653575080600481111561164f57fe5b6002145b15156116655761061c6201a1f961180f565b600061166f610679565b91506003905081600481111561168157fe5b106116925761061c6201a1f961180f565b600954600160a060020a038b81169116146116ac57600080fd5b8715156116b857600080fd5b6006546005549096509450856116d4868a63ffffffff61192316565b11156116ed576116ea868663ffffffff61193916565b97505b6116fd858963ffffffff61192316565b600555600160a060020a038a1663a9059cbb8a8a60006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b151561175d57600080fd5b6102c65a03f1151561176e57600080fd5b50505060405180519050151561178357600080fd5b6117ee8a600160a060020a031663cb4e75bb6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156117cc57600080fd5b6102c65a03f115156117dd57600080fd5b505050604051805190508a8a61194b565b60019650505050505b50509392505050565b600954600160a060020a031681565b60007f2e36a7093f25f22bd4cbdeb6040174c3ba4c5fe8f1abc04e7c3c48f26c7413e08260405190815260200160405180910390a15090565b7fcd2525d5f744a73d0628d3559e6307b563577eef6e90395c5345d56251e6811560405160405180910390a1565b7e47706786c922d17b39285dc59d696bafea72c0b003d3841ae1202076f4c2e481604051600160a060020a03909116815260200160405180910390a150565b7f9c8e7d83025bef8a04c664b2f753f64b8814bdb7e27291d7e50935f18cc3c71281604051600160a060020a03909116815260200160405180910390a150565b7f32fc160bbed8ee6cd2b58d0c9e99c310c62dd70084e16ef451ba3deef6cb079d60405160405180910390a1565b60008282018381101561193257fe5b9392505050565b60008282111561194557fe5b50900390565b7f3e501db90d29a8b80c5dbafec3fbc8a0256516a56ef879411a72d8057ca39f59838383604051928352600160a060020a0390911660208301526040808301919091526060909101905180910390a15050505600a165627a7a72305820a37719b6b53b9dbd352cca135102ae823c1689d047a192824d0a96760ffcc2c10029000000000000000000000000a668a4148f348f3fc8d1f614232742e4da641ac3000000000000000000000000df6ef343350780bf8c3410bf062e0c015b1dd671000000000000000000000000810000cd3982e4094e9e0f3cb972ae8bf91b1b1c000000000000000000000000000000000000000000000000000000005b6451d0000000000000000000000000000000000000000000000000000000005d45855000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000de0b6b3a7640001

Deployed Bytecode

0x6060604052600436106101715763ffffffff60e060020a600035041663067906b181146101765780630b97bc86146101a55780630bf1c747146101ca5780630c3c92a3146101f15780631865c57d14610204578063205b931e146102505780632be4a9031461026e5780633f242990146102bd57806341d4a1ab146102d057806345644fd6146102e35780634592cd1d14610301578063557f4bc9146103145780635aa77d3c14610333578063700c94741461034657806383197ef01461039557806392c9a9e2146103aa5780639b19251a146103bd578063addd5099146103dc578063bca19900146103fb578063c0ee0b8a1461040e578063c24a0f8b1461043d578063c32ee59114610450578063c661deb414610484578063c875b1fb146104ac578063cb9bdf45146104bf578063ce606ee0146104d2578063d8f9659b146104e5578063d8fed39e1461053f578063e1c7392a14610552578063fbf22dea14610565578063fc0c546a1461058d575b600080fd5b341561018157600080fd5b6101896105a0565b604051600160a060020a03909116815260200160405180910390f35b34156101b057600080fd5b6101b86105af565b60405190815260200160405180910390f35b34156101d557600080fd5b6101dd6105b5565b604051901515815260200160405180910390f35b34156101fc57600080fd5b6101b86105be565b341561020f57600080fd5b610217610679565b6040518083600481111561022757fe5b60ff16815260200182600481111561023b57fe5b60ff1681526020019250505060405180910390f35b341561025b57600080fd5b6101b86004803560248101910135610726565b341561027957600080fd5b6101b860046024813581810190830135806020818102016040519081016040528093929190818152602001838360200280828437509496506107e995505050505050565b34156102c857600080fd5b6101b86108cd565b34156102db57600080fd5b6101896108d7565b34156102ee57600080fd5b6101b860048035602481019101356108e6565b341561030c57600080fd5b6101dd610998565b341561031f57600080fd5b6101dd600160a060020a03600435166109ef565b341561033e57600080fd5b610189610a4e565b341561035157600080fd5b6101b86004602481358181019083013580602081810201604051908101604052809392919081815260200183836020028082843750949650610a5d95505050505050565b34156103a057600080fd5b6103a8610b3d565b005b34156103b557600080fd5b6101b8610b62565b34156103c857600080fd5b6101dd600160a060020a0360043516610bf5565b34156103e757600080fd5b6101dd600160a060020a0360043516610c0a565b341561040657600080fd5b6101b8610c1f565b341561041957600080fd5b6103a860048035600160a060020a0316906024803591604435918201910135610c29565b341561044857600080fd5b6101b8610cd8565b341561045b57600080fd5b6101dd600160a060020a0360043581169060243581169060443581169060643516608435610cde565b341561048f57600080fd5b6101b8600160a060020a0360043581169060243516604435610d83565b34156104b757600080fd5b6101b861108d565b34156104ca57600080fd5b6101b86112d1565b34156104dd57600080fd5b6101896112d7565b34156104f057600080fd5b6101b8600460248135818101908301358060208181020160405190810160405280939291908181526020018383602002808284375094965050509235600160a060020a031692506112e6915050565b341561054a57600080fd5b6101b8611435565b341561055d57600080fd5b6101b861143b565b341561057057600080fd5b6101b8600160a060020a03600435811690602435166044356115d7565b341561059857600080fd5b610189611800565b600b54600160a060020a031681565b60035481565b600d5460ff1681565b6000805433600160a060020a0390811691161415610676576000806105e1610679565b915091508160048111156105f157fe5b6002148061060a575080600481111561060657fe5b6002145b151561062a5761061c6201a1f961180f565b506201a1f960005260206000f35b6000610634610679565b509050600381600481111561064557fe5b106106565761061c6201a1f961180f565b600d805461ff00191661010017905561066d611848565b600193505b5050505b90565b600080600080600d60029054906101000a900460ff16156106a05760008093509350610720565b600d5460ff16156106b75760048093509350610720565b6003544210156106cd5760018093509350610720565b600d54610100900460ff16806106e65750600854600754145b806106f2575060045442115b6106fd576002610700565b60035b915060065460055414610714576002610717565b60035b90508181935093505b50509091565b600080548190819033600160a060020a03908116911614156107e157600091505b838210156107dc5784848381811061075b57fe5b90506020020135600160a060020a0316905080600160a060020a03166000141580156107a05750600160a060020a03811660009081526002602052604090205460ff16155b156107d157600160a060020a0381166000908152600260205260409020805460ff191660011790556107d181611876565b816001019150610747565b600192505b505092915050565b600160a060020a033316600090815260026020526040812054819060ff1680610820575060005433600160a060020a039081169116145b156108c757600080610830610679565b9150915081600481111561084057fe5b60021480610859575080600481111561085557fe5b6002145b151561086b5761061c6201a1f961180f565b600092505b84518310156108c057600c600086858151811061088957fe5b90602001906020020151600160a060020a031681526020810191909152604001600020805460ff1916905560019290920191610870565b6001935050505b50919050565b6008546006540190565b600a54600160a060020a031681565b600080548190819033600160a060020a03908116911614156107e157600091505b838210156107dc5784848381811061091b57fe5b90506020020135600160a060020a0316905080600160a060020a031660001415801561095f5750600160a060020a03811660009081526002602052604090205460ff165b1561098d57600160a060020a0381166000908152600260205260409020805460ff1916905561098d816118b5565b816001019150610907565b60015460009033600160a060020a039081169116146109b957506000610676565b50600180546000805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a0384161790915516815590565b6000805433600160a060020a0390811691161415610a4957600160a060020a0382161515610a1f57506000610a49565b506001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161781555b919050565b600154600160a060020a031681565b600160a060020a033316600090815260026020526040812054819060ff1680610a94575060005433600160a060020a039081169116145b156108c757600080610aa4610679565b91509150816004811115610ab457fe5b60021480610acd5750806004811115610ac957fe5b6002145b1515610adf5761061c6201a1f961180f565b600092505b84518310156108c0576001600c6000878681518110610aff57fe5b90602001906020020151600160a060020a031681526020810191909152604001600020805460ff191691151591909117905560019290920191610ae4565b60005433600160a060020a0390811691161415610b605733600160a060020a0316ff5b565b6000805433600160a060020a039081169116141561067657600080610b85610679565b90925090506003826004811115610b9857fe5b1080610baf57506003816004811115610bad57fe5b105b15610bc05761061c6201a1f961180f565b600d5460ff1615610bd75761061c6201a1f961180f565b600d805460ff19166001179055610bec6118f5565b60019250505090565b600c6020526000908152604090205460ff1681565b60026020526000908152604090205460ff1681565b6007546006540190565b600954600160a060020a0316630e6d1de96000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610c7157600080fd5b6102c65a03f11515610c8257600080fd5b50505060405180519050600160a060020a031633600160a060020a0316141515610cab57600080fd5b600160a060020a03841660009081526002602052604090205460ff161515610cd257600080fd5b50505050565b60045481565b600954600090600160a060020a038481169116148015610d715750600160a060020a03861660009081526002602052604090205460ff168015610d32575030600160a060020a031685600160a060020a0316145b80610d71575030600160a060020a031686600160a060020a0316148015610d715750600160a060020a0385166000908152600c602052604090205460ff165b15610d7a575060015b95945050505050565b600160a060020a03331660009081526002602052604081205481908190819060ff161561108357600160a060020a0386166000908152600c6020526040902054869060ff161561108157600080610dd8610679565b91509150816004811115610de857fe5b60021480610e015750806004811115610dfd57fe5b6002145b1515610e135761061c6201a1f961180f565b6000610e1d610679565b5090506003816004811115610e2e57fe5b10610e3f5761061c6201a1f961180f565b600954600160a060020a038c8116911614610e5957600080fd5b881515610e6557600080fd5b600854600754909750955086610e81878b63ffffffff61192316565b1115610e9a57610e97878763ffffffff61193916565b98505b610eaa868a63ffffffff61192316565b600755600160a060020a038b1663cb4e75bb6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610ef357600080fd5b6102c65a03f11515610f0457600080fd5b5050506040518051955050600160a060020a038b16634bde38c86000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610f5557600080fd5b6102c65a03f11515610f6657600080fd5b50505060405180519050600160a060020a031663e0873c06868b60006040516020015260405160e060020a63ffffffff851602815260048101929092526024820152604401602060405180830381600087803b1515610fc457600080fd5b6102c65a03f11515610fd557600080fd5b50505060405180516001149050610feb57600080fd5b8a600160a060020a031663a9059cbb8b8b60006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b151561104857600080fd5b6102c65a03f1151561105957600080fd5b50505060405180519050151561106e57600080fd5b611079858b8b61194b565b600197505050505b505b5050509392505050565b600160a060020a03331660009081526002602052604081205481908190819060ff16806110c8575060005433600160a060020a039081169116145b15610672576000806110d8610679565b909250905060038260048111156110eb57fe5b10806111025750600381600481111561110057fe5b105b156111135761061c6201a1f961180f565b600d5460ff161561112a5761061c6201a1f961180f565b600a54600160a060020a03169450846370a082313060006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b151561118657600080fd5b6102c65a03f1151561119757600080fd5b50505060405180519450508315156111bc576111b56201a1fa61180f565b95506112c9565b600b54600160a060020a039081169350851663095ea7b3848660006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b151561122157600080fd5b6102c65a03f1151561123257600080fd5b50505060405180519050151561124e576111b56201a1fb61180f565b82600160a060020a0316630d80fcdb8560006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561129d57600080fd5b6102c65a03f115156112ae57600080fd5b505050604051805160011490506112c457600080fd5b600195505b505050505090565b60055481565b600054600160a060020a031681565b6000805481908190819033600160a060020a039081169116141561142c57600092505b85518310156114275785838151811061131e57fe5b90602001906020020151915081600160a060020a03166370a082313060006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b151561138157600080fd5b6102c65a03f1151561139257600080fd5b5050506040518051915050801561141c5781600160a060020a031663a9059cbb868360006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b151561140057600080fd5b6102c65a03f1151561141157600080fd5b505050604051805150505b600190920191611309565b600193505b50505092915050565b60065481565b60008054819033600160a060020a03908116911614156115d357600061145f610679565b509050600081600481111561147057fe5b146114815761061c6201a1f961180f565b600d805462ff000019169055600954600160a060020a031663cb4e75bb6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156114d557600080fd5b6102c65a03f115156114e657600080fd5b5050506040518051600954909350600160a060020a03169050634bde38c86000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561153b57600080fd5b6102c65a03f1151561154c57600080fd5b50505060405180519050600160a060020a031663e0873c068360065460006040516020015260405160e060020a63ffffffff851602815260048101929092526024820152604401602060405180830381600087803b15156115ac57600080fd5b6102c65a03f115156115bd57600080fd5b50505060405180516001149050610bec57600080fd5b5090565b600160a060020a0333166000908152600260205260408120548190819060ff16156117f757600160a060020a0385166000908152600c6020526040902054859060ff16156110835760008061162a610679565b9150915081600481111561163a57fe5b60021480611653575080600481111561164f57fe5b6002145b15156116655761061c6201a1f961180f565b600061166f610679565b91506003905081600481111561168157fe5b106116925761061c6201a1f961180f565b600954600160a060020a038b81169116146116ac57600080fd5b8715156116b857600080fd5b6006546005549096509450856116d4868a63ffffffff61192316565b11156116ed576116ea868663ffffffff61193916565b97505b6116fd858963ffffffff61192316565b600555600160a060020a038a1663a9059cbb8a8a60006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b151561175d57600080fd5b6102c65a03f1151561176e57600080fd5b50505060405180519050151561178357600080fd5b6117ee8a600160a060020a031663cb4e75bb6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156117cc57600080fd5b6102c65a03f115156117dd57600080fd5b505050604051805190508a8a61194b565b60019650505050505b50509392505050565b600954600160a060020a031681565b60007f2e36a7093f25f22bd4cbdeb6040174c3ba4c5fe8f1abc04e7c3c48f26c7413e08260405190815260200160405180910390a15090565b7fcd2525d5f744a73d0628d3559e6307b563577eef6e90395c5345d56251e6811560405160405180910390a1565b7e47706786c922d17b39285dc59d696bafea72c0b003d3841ae1202076f4c2e481604051600160a060020a03909116815260200160405180910390a150565b7f9c8e7d83025bef8a04c664b2f753f64b8814bdb7e27291d7e50935f18cc3c71281604051600160a060020a03909116815260200160405180910390a150565b7f32fc160bbed8ee6cd2b58d0c9e99c310c62dd70084e16ef451ba3deef6cb079d60405160405180910390a1565b60008282018381101561193257fe5b9392505050565b60008282111561194557fe5b50900390565b7f3e501db90d29a8b80c5dbafec3fbc8a0256516a56ef879411a72d8057ca39f59838383604051928352600160a060020a0390911660208301526040808301919091526060909101905180910390a15050505600a165627a7a72305820a37719b6b53b9dbd352cca135102ae823c1689d047a192824d0a96760ffcc2c10029

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

000000000000000000000000a668a4148f348f3fc8d1f614232742e4da641ac3000000000000000000000000df6ef343350780bf8c3410bf062e0c015b1dd671000000000000000000000000810000cd3982e4094e9e0f3cb972ae8bf91b1b1c000000000000000000000000000000000000000000000000000000005b6451d0000000000000000000000000000000000000000000000000000000005d45855000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000de0b6b3a7640001

-----Decoded View---------------
Arg [0] : _token (address): 0xa668a4148F348f3FC8D1F614232742e4dA641aC3
Arg [1] : _bonusToken (address): 0xDf6Ef343350780BF8C3410BF062e0C015B1DD671
Arg [2] : _profiterole (address): 0x810000Cd3982e4094e9e0F3CB972ae8bF91b1B1C
Arg [3] : _startDate (uint256): 1533301200
Arg [4] : _endDate (uint256): 1564837200
Arg [5] : _tokenSoftcap (uint256): 1
Arg [6] : _tokenHardcap (uint256): 1000000000000000001

-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 000000000000000000000000a668a4148f348f3fc8d1f614232742e4da641ac3
Arg [1] : 000000000000000000000000df6ef343350780bf8c3410bf062e0c015b1dd671
Arg [2] : 000000000000000000000000810000cd3982e4094e9e0f3cb972ae8bf91b1b1c
Arg [3] : 000000000000000000000000000000000000000000000000000000005b6451d0
Arg [4] : 000000000000000000000000000000000000000000000000000000005d458550
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [6] : 0000000000000000000000000000000000000000000000000de0b6b3a7640001


Swarm Source

bzzr://a37719b6b53b9dbd352cca135102ae823c1689d047a192824d0a96760ffcc2c1

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

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.