ETH Price: $3,483.96 (-0.20%)

Token

Greyp (GRP)
 

Overview

Max Total Supply

11,000,000 GRP

Holders

1,034

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 0 Decimals)

Filtered by Token Holder
batsu.eth
Balance
686 GRP

Value
$0.00
0xf1ca4Bf4C325C3078Ec25299601A519eBc6BEA6D
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
EquityToken

Compiler Version
v0.4.26+commit.4563c3fc

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

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

pragma solidity 0.4.26;

/// @title provides subject to role checking logic
contract IAccessPolicy {

    ////////////////////////
    // Public functions
    ////////////////////////

    /// @notice We don't make this function constant to allow for state-updating access controls such as rate limiting.
    /// @dev checks if subject belongs to requested role for particular object
    /// @param subject address to be checked against role, typically msg.sender
    /// @param role identifier of required role
    /// @param object contract instance context for role checking, typically contract requesting the check
    /// @param verb additional data, in current AccessControll implementation msg.sig
    /// @return if subject belongs to a role
    function allowed(
        address subject,
        bytes32 role,
        address object,
        bytes4 verb
    )
        public
        returns (bool);
}

/// @title enables access control in implementing contract
/// @dev see AccessControlled for implementation
contract IAccessControlled {

    ////////////////////////
    // Events
    ////////////////////////

    /// @dev must log on access policy change
    event LogAccessPolicyChanged(
        address controller,
        IAccessPolicy oldPolicy,
        IAccessPolicy newPolicy
    );

    ////////////////////////
    // Public functions
    ////////////////////////

    /// @dev allows to change access control mechanism for this contract
    ///     this method must be itself access controlled, see AccessControlled implementation and notice below
    /// @notice it is a huge issue for Solidity that modifiers are not part of function signature
    ///     then interfaces could be used for example to control access semantics
    /// @param newPolicy new access policy to controll this contract
    /// @param newAccessController address of ROLE_ACCESS_CONTROLLER of new policy that can set access to this contract
    function setAccessPolicy(IAccessPolicy newPolicy, address newAccessController)
        public;

    function accessPolicy()
        public
        constant
        returns (IAccessPolicy);

}

contract StandardRoles {

    ////////////////////////
    // Constants
    ////////////////////////

    // @notice Soldity somehow doesn't evaluate this compile time
    // @dev role which has rights to change permissions and set new policy in contract, keccak256("AccessController")
    bytes32 internal constant ROLE_ACCESS_CONTROLLER = 0xac42f8beb17975ed062dcb80c63e6d203ef1c2c335ced149dc5664cc671cb7da;
}

/// @title Granular code execution permissions
/// @notice Intended to replace existing Ownable pattern with more granular permissions set to execute smart contract functions
///     for each function where 'only' modifier is applied, IAccessPolicy implementation is called to evaluate if msg.sender belongs to required role for contract being called.
///     Access evaluation specific belong to IAccessPolicy implementation, see RoleBasedAccessPolicy for details.
/// @dev Should be inherited by a contract requiring such permissions controll. IAccessPolicy must be provided in constructor. Access policy may be replaced to a different one
///     by msg.sender with ROLE_ACCESS_CONTROLLER role
contract AccessControlled is IAccessControlled, StandardRoles {

    ////////////////////////
    // Mutable state
    ////////////////////////

    IAccessPolicy private _accessPolicy;

    ////////////////////////
    // Modifiers
    ////////////////////////

    /// @dev limits function execution only to senders assigned to required 'role'
    modifier only(bytes32 role) {
        require(_accessPolicy.allowed(msg.sender, role, this, msg.sig));
        _;
    }

    ////////////////////////
    // Constructor
    ////////////////////////

    constructor(IAccessPolicy policy) internal {
        require(address(policy) != 0x0);
        _accessPolicy = policy;
    }

    ////////////////////////
    // Public functions
    ////////////////////////

    //
    // Implements IAccessControlled
    //

    function setAccessPolicy(IAccessPolicy newPolicy, address newAccessController)
        public
        only(ROLE_ACCESS_CONTROLLER)
    {
        // ROLE_ACCESS_CONTROLLER must be present
        // under the new policy. This provides some
        // protection against locking yourself out.
        require(newPolicy.allowed(newAccessController, ROLE_ACCESS_CONTROLLER, this, msg.sig));

        // We can now safely set the new policy without foot shooting.
        IAccessPolicy oldPolicy = _accessPolicy;
        _accessPolicy = newPolicy;

        // Log event
        emit LogAccessPolicyChanged(msg.sender, oldPolicy, newPolicy);
    }

    function accessPolicy()
        public
        constant
        returns (IAccessPolicy)
    {
        return _accessPolicy;
    }
}

/// @title standard access roles of the Platform
/// @dev constants are kept in CODE not in STORAGE so they are comparatively cheap
contract AccessRoles {

    ////////////////////////
    // Constants
    ////////////////////////

    // NOTE: All roles are set to the keccak256 hash of the
    // CamelCased role name, i.e.
    // ROLE_LOCKED_ACCOUNT_ADMIN = keccak256("LockedAccountAdmin")

    // May issue (generate) Neumarks
    bytes32 internal constant ROLE_NEUMARK_ISSUER = 0x921c3afa1f1fff707a785f953a1e197bd28c9c50e300424e015953cbf120c06c;

    // May burn Neumarks it owns
    bytes32 internal constant ROLE_NEUMARK_BURNER = 0x19ce331285f41739cd3362a3ec176edffe014311c0f8075834fdd19d6718e69f;

    // May create new snapshots on Neumark
    bytes32 internal constant ROLE_SNAPSHOT_CREATOR = 0x08c1785afc57f933523bc52583a72ce9e19b2241354e04dd86f41f887e3d8174;

    // May enable/disable transfers on Neumark
    bytes32 internal constant ROLE_TRANSFER_ADMIN = 0xb6527e944caca3d151b1f94e49ac5e223142694860743e66164720e034ec9b19;

    // may reclaim tokens/ether from contracts supporting IReclaimable interface
    bytes32 internal constant ROLE_RECLAIMER = 0x0542bbd0c672578966dcc525b30aa16723bb042675554ac5b0362f86b6e97dc5;

    // represents legally platform operator in case of forks and contracts with legal agreement attached. keccak256("PlatformOperatorRepresentative")
    bytes32 internal constant ROLE_PLATFORM_OPERATOR_REPRESENTATIVE = 0xb2b321377653f655206f71514ff9f150d0822d062a5abcf220d549e1da7999f0;

    // may setup whitelists and abort whitelisting contract with curve rollback
    bytes32 internal constant ROLE_WHITELIST_ADMIN = 0xaef456e7c864418e1d2a40d996ca4febf3a7e317fe3af5a7ea4dda59033bbe5c;

    // allows to deposit EUR-T and allow addresses to send and receive EUR-T. keccak256("EurtDepositManager")
    bytes32 internal constant ROLE_EURT_DEPOSIT_MANAGER = 0x7c8ecdcba80ce87848d16ad77ef57cc196c208fc95c5638e4a48c681a34d4fe7;

    // allows to register identities and change associated claims keccak256("IdentityManager")
    bytes32 internal constant ROLE_IDENTITY_MANAGER = 0x32964e6bc50f2aaab2094a1d311be8bda920fc4fb32b2fb054917bdb153a9e9e;

    // allows to replace controller on euro token and to destroy tokens without withdraw kecckak256("EurtLegalManager")
    bytes32 internal constant ROLE_EURT_LEGAL_MANAGER = 0x4eb6b5806954a48eb5659c9e3982d5e75bfb2913f55199877d877f157bcc5a9b;

    // allows to change known interfaces in universe kecckak256("UniverseManager")
    bytes32 internal constant ROLE_UNIVERSE_MANAGER = 0xe8d8f8f9ea4b19a5a4368dbdace17ad71a69aadeb6250e54c7b4c7b446301738;

    // allows to exchange gas for EUR-T keccak("GasExchange")
    bytes32 internal constant ROLE_GAS_EXCHANGE = 0x9fe43636e0675246c99e96d7abf9f858f518b9442c35166d87f0934abef8a969;

    // allows to set token exchange rates keccak("TokenRateOracle")
    bytes32 internal constant ROLE_TOKEN_RATE_ORACLE = 0xa80c3a0c8a5324136e4c806a778583a2a980f378bdd382921b8d28dcfe965585;

    // allows to disburse to the fee disbursal contract keccak("Disburser")
    bytes32 internal constant ROLE_DISBURSER = 0xd7ea6093d11d866c9e8449f8bffd9da1387c530ee40ad54f0641425bb0ca33b7;

    // allows to manage feedisbursal controller keccak("DisbursalManager")
    bytes32 internal constant ROLE_DISBURSAL_MANAGER = 0x677f87f7b7ef7c97e42a7e6c85c295cf020c9f11eea1e49f6bf847d7aeae1475;

    // allows to upgrade company/issuer contracts which are also equity token controllers keccak("CompanyUpgradeAdmin")
    bytes32 internal constant ROLE_COMPANY_UPGRADE_ADMIN = 0xfef15747c403732d986b29a92a880d8f2fb886b99417c8bbef226f85885ca924;
}

contract IEthereumForkArbiter {

    ////////////////////////
    // Events
    ////////////////////////

    event LogForkAnnounced(
        string name,
        string url,
        uint256 blockNumber
    );

    event LogForkSigned(
        uint256 blockNumber,
        bytes32 blockHash
    );

    ////////////////////////
    // Public functions
    ////////////////////////

    function nextForkName()
        public
        constant
        returns (string);

    function nextForkUrl()
        public
        constant
        returns (string);

    function nextForkBlockNumber()
        public
        constant
        returns (uint256);

    function lastSignedBlockNumber()
        public
        constant
        returns (uint256);

    function lastSignedBlockHash()
        public
        constant
        returns (bytes32);

    function lastSignedTimestamp()
        public
        constant
        returns (uint256);

}

/**
 * @title legally binding smart contract
 * @dev General approach to paring legal and smart contracts:
 * 1. All terms and agreement are between two parties: here between smart conctract legal representation and platform investor.
 * 2. Parties are represented by public Ethereum addresses. Platform investor is and address that holds and controls funds and receives and controls Neumark token
 * 3. Legal agreement has immutable part that corresponds to smart contract code and mutable part that may change for example due to changing regulations or other externalities that smart contract does not control.
 * 4. There should be a provision in legal document that future changes in mutable part cannot change terms of immutable part.
 * 5. Immutable part links to corresponding smart contract via its address.
 * 6. Additional provision should be added if smart contract supports it
 *  a. Fork provision
 *  b. Bugfixing provision (unilateral code update mechanism)
 *  c. Migration provision (bilateral code update mechanism)
 *
 * Details on Agreement base class:
 * 1. We bind smart contract to legal contract by storing uri (preferably ipfs or hash) of the legal contract in the smart contract. It is however crucial that such binding is done by smart contract legal representation so transaction establishing the link must be signed by respective wallet ('amendAgreement')
 * 2. Mutable part of agreement may change. We should be able to amend the uri later. Previous amendments should not be lost and should be retrievable (`amendAgreement` and 'pastAgreement' functions).
 * 3. It is up to deriving contract to decide where to put 'acceptAgreement' modifier. However situation where there is no cryptographic proof that given address was really acting in the transaction should be avoided, simplest example being 'to' address in `transfer` function of ERC20.
 *
**/
contract IAgreement {

    ////////////////////////
    // Events
    ////////////////////////

    event LogAgreementAccepted(
        address indexed accepter
    );

    event LogAgreementAmended(
        address contractLegalRepresentative,
        string agreementUri
    );

    /// @dev should have access restrictions so only contractLegalRepresentative may call
    function amendAgreement(string agreementUri) public;

    /// returns information on last amendment of the agreement
    /// @dev MUST revert if no agreements were set
    function currentAgreement()
        public
        constant
        returns
        (
            address contractLegalRepresentative,
            uint256 signedBlockTimestamp,
            string agreementUri,
            uint256 index
        );

    /// returns information on amendment with index
    /// @dev MAY revert on non existing amendment, indexing starts from 0
    function pastAgreement(uint256 amendmentIndex)
        public
        constant
        returns
        (
            address contractLegalRepresentative,
            uint256 signedBlockTimestamp,
            string agreementUri,
            uint256 index
        );

    /// returns the number of block at wchich `signatory` signed agreement
    /// @dev MUST return 0 if not signed
    function agreementSignedAtBlock(address signatory)
        public
        constant
        returns (uint256 blockNo);

    /// returns number of amendments made by contractLegalRepresentative
    function amendmentsCount()
        public
        constant
        returns (uint256);
}

/**
 * @title legally binding smart contract
 * @dev read IAgreement for details
**/
contract Agreement is
    IAgreement,
    AccessControlled,
    AccessRoles
{

    ////////////////////////
    // Type declarations
    ////////////////////////

    /// @notice agreement with signature of the platform operator representative
    struct SignedAgreement {
        address contractLegalRepresentative;
        uint256 signedBlockTimestamp;
        string agreementUri;
    }

    ////////////////////////
    // Immutable state
    ////////////////////////

    IEthereumForkArbiter private ETHEREUM_FORK_ARBITER;

    ////////////////////////
    // Mutable state
    ////////////////////////

    // stores all amendments to the agreement, first amendment is the original
    SignedAgreement[] private _amendments;

    // stores block numbers of all addresses that signed the agreement (signatory => block number)
    mapping(address => uint256) private _signatories;

    ////////////////////////
    // Modifiers
    ////////////////////////

    /// @notice logs that agreement was accepted by platform user
    /// @dev intended to be added to functions that if used make 'accepter' origin to enter legally binding agreement
    modifier acceptAgreement(address accepter) {
        acceptAgreementInternal(accepter);
        _;
    }

    modifier onlyLegalRepresentative(address legalRepresentative) {
        require(mCanAmend(legalRepresentative));
        _;
    }

    ////////////////////////
    // Constructor
    ////////////////////////

    constructor(IAccessPolicy accessPolicy, IEthereumForkArbiter forkArbiter)
        AccessControlled(accessPolicy)
        internal
    {
        require(forkArbiter != IEthereumForkArbiter(0x0));
        ETHEREUM_FORK_ARBITER = forkArbiter;
    }

    ////////////////////////
    // Public functions
    ////////////////////////

    function amendAgreement(string agreementUri)
        public
        onlyLegalRepresentative(msg.sender)
    {
        SignedAgreement memory amendment = SignedAgreement({
            contractLegalRepresentative: msg.sender,
            signedBlockTimestamp: block.timestamp,
            agreementUri: agreementUri
        });
        _amendments.push(amendment);
        emit LogAgreementAmended(msg.sender, agreementUri);
    }

    function ethereumForkArbiter()
        public
        constant
        returns (IEthereumForkArbiter)
    {
        return ETHEREUM_FORK_ARBITER;
    }

    function currentAgreement()
        public
        constant
        returns
        (
            address contractLegalRepresentative,
            uint256 signedBlockTimestamp,
            string agreementUri,
            uint256 index
        )
    {
        require(_amendments.length > 0);
        uint256 last = _amendments.length - 1;
        SignedAgreement storage amendment = _amendments[last];
        return (
            amendment.contractLegalRepresentative,
            amendment.signedBlockTimestamp,
            amendment.agreementUri,
            last
        );
    }

    function pastAgreement(uint256 amendmentIndex)
        public
        constant
        returns
        (
            address contractLegalRepresentative,
            uint256 signedBlockTimestamp,
            string agreementUri,
            uint256 index
        )
    {
        SignedAgreement storage amendment = _amendments[amendmentIndex];
        return (
            amendment.contractLegalRepresentative,
            amendment.signedBlockTimestamp,
            amendment.agreementUri,
            amendmentIndex
        );
    }

    function agreementSignedAtBlock(address signatory)
        public
        constant
        returns (uint256 blockNo)
    {
        return _signatories[signatory];
    }

    function amendmentsCount()
        public
        constant
        returns (uint256)
    {
        return _amendments.length;
    }

    ////////////////////////
    // Internal functions
    ////////////////////////

    /// provides direct access to derived contract
    function acceptAgreementInternal(address accepter)
        internal
    {
        if(_signatories[accepter] == 0) {
            require(_amendments.length > 0);
            _signatories[accepter] = block.number;
            emit LogAgreementAccepted(accepter);
        }
    }

    //
    // MAgreement Internal interface (todo: extract)
    //

    /// default amend permission goes to ROLE_PLATFORM_OPERATOR_REPRESENTATIVE
    function mCanAmend(address legalRepresentative)
        internal
        returns (bool)
    {
        return accessPolicy().allowed(legalRepresentative, ROLE_PLATFORM_OPERATOR_REPRESENTATIVE, this, msg.sig);
    }
}

contract Math {

    ////////////////////////
    // Internal functions
    ////////////////////////

    // absolute difference: |v1 - v2|
    function absDiff(uint256 v1, uint256 v2)
        internal
        pure
        returns(uint256)
    {
        return v1 > v2 ? v1 - v2 : v2 - v1;
    }

    // divide v by d, round up if remainder is 0.5 or more
    function divRound(uint256 v, uint256 d)
        internal
        pure
        returns(uint256)
    {
        return add(v, d/2) / d;
    }

    // computes decimal decimalFraction 'frac' of 'amount' with maximum precision (multiplication first)
    // both amount and decimalFraction must have 18 decimals precision, frac 10**18 represents a whole (100% of) amount
    // mind loss of precision as decimal fractions do not have finite binary expansion
    // do not use instead of division
    function decimalFraction(uint256 amount, uint256 frac)
        internal
        pure
        returns(uint256)
    {
        // it's like 1 ether is 100% proportion
        return proportion(amount, frac, 10**18);
    }

    // computes part/total of amount with maximum precision (multiplication first)
    // part and total must have the same units
    function proportion(uint256 amount, uint256 part, uint256 total)
        internal
        pure
        returns(uint256)
    {
        return divRound(mul(amount, part), total);
    }

    //
    // Open Zeppelin Math library below
    //

    function mul(uint256 a, uint256 b)
        internal
        pure
        returns (uint256)
    {
        uint256 c = a * b;
        assert(a == 0 || c / a == b);
        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;
    }

    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 ? a : b;
    }
}

/// @title uniquely identifies deployable (non-abstract) platform contract
/// @notice cheap way of assigning implementations to knownInterfaces which represent system services
///         unfortunatelly ERC165 does not include full public interface (ABI) and does not provide way to list implemented interfaces
///         EIP820 still in the making
/// @dev ids are generated as follows keccak256("neufund-platform:<contract name>")
///      ids roughly correspond to ABIs
contract IContractId {
    /// @param id defined as above
    /// @param version implementation version
    function contractId() public pure returns (bytes32 id, uint256 version);
}

// version history as per contract id
// 0 - initial version
// 1 - added SHARE_NOMINAL_VALUE_ULPS, SHARE_NOMINAL_VALUE_EUR_ULPS, TOKEN_NAME, TOKEN_SYMBOL, SHARE_PRICE


/// @title sets terms for tokens in ETO
contract ETOTokenTerms is Math, IContractId {

    ////////////////////////
    // Constants state
    ////////////////////////

    bytes32 private constant EMPTY_STRING_HASH = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
    // equity tokens decimals (precision)
    uint8 public constant EQUITY_TOKENS_PRECISION = 0; // indivisible

    ////////////////////////
    // Immutable state
    ////////////////////////

    // equity token metadata
    string public EQUITY_TOKEN_NAME;
    string public EQUITY_TOKEN_SYMBOL;

    // minimum number of tokens being offered. will set min cap
    uint256 public MIN_NUMBER_OF_TOKENS;
    // maximum number of tokens being offered. will set max cap
    uint256 public MAX_NUMBER_OF_TOKENS;
    // base token price in EUR-T, without any discount scheme
    uint256 public TOKEN_PRICE_EUR_ULPS;
    // maximum number of tokens in whitelist phase
    uint256 public MAX_NUMBER_OF_TOKENS_IN_WHITELIST;
    // sets nominal value of newly issued shares in currency of share capital as per ISHA
    // will be embedded in the equity token (IEquityToken interface)
    uint256 public SHARE_NOMINAL_VALUE_ULPS;
    // sets nominal value of newly issued shares in euro, used to withdraw share capital to Nominee
    uint256 public SHARE_NOMINAL_VALUE_EUR_ULPS;
    // equity tokens per share
    uint256 public EQUITY_TOKENS_PER_SHARE;


    ////////////////////////
    // Constructor
    ////////////////////////

    constructor(
        string equityTokenName,
        string equityTokenSymbol,
        uint256 minNumberOfTokens,
        uint256 maxNumberOfTokens,
        uint256 tokenPriceEurUlps,
        uint256 maxNumberOfTokensInWhitelist,
        uint256 shareNominalValueUlps,
        uint256 shareNominalValueEurUlps,
        uint256 equityTokensPerShare
    )
        public
    {
        require(maxNumberOfTokens >= maxNumberOfTokensInWhitelist, "NF_WL_TOKENS_GT_MAX_TOKENS");
        require(maxNumberOfTokens >= minNumberOfTokens, "NF_MIN_TOKENS_GT_MAX_TOKENS");
        // min cap must be > single share
        require(minNumberOfTokens >= equityTokensPerShare, "NF_ETO_TERMS_ONE_SHARE");
        // maximum number of tokens are full shares
        require(maxNumberOfTokens % equityTokensPerShare == 0, "NF_MAX_TOKENS_FULL_SHARES");
        require(shareNominalValueUlps > 0);
        require(shareNominalValueEurUlps > 0);
        require(equityTokensPerShare > 0);
        require(keccak256(abi.encodePacked(equityTokenName)) != EMPTY_STRING_HASH);
        require(keccak256(abi.encodePacked(equityTokenSymbol)) != EMPTY_STRING_HASH);
        // overflows cannot be possible
        require(maxNumberOfTokens < 2**56, "NF_TOO_MANY_TOKENS");
        require(mul(tokenPriceEurUlps, maxNumberOfTokens) < 2**112, "NF_TOO_MUCH_FUNDS_COLLECTED");

        MIN_NUMBER_OF_TOKENS = minNumberOfTokens;
        MAX_NUMBER_OF_TOKENS = maxNumberOfTokens;
        TOKEN_PRICE_EUR_ULPS = tokenPriceEurUlps;
        MAX_NUMBER_OF_TOKENS_IN_WHITELIST = maxNumberOfTokensInWhitelist;
        SHARE_NOMINAL_VALUE_EUR_ULPS = shareNominalValueEurUlps;
        SHARE_NOMINAL_VALUE_ULPS = shareNominalValueUlps;
        EQUITY_TOKEN_NAME = equityTokenName;
        EQUITY_TOKEN_SYMBOL = equityTokenSymbol;
        EQUITY_TOKENS_PER_SHARE = equityTokensPerShare;
    }

    ////////////////////////
    // Public methods
    ////////////////////////

    function SHARE_PRICE_EUR_ULPS() public constant returns (uint256) {
        return mul(TOKEN_PRICE_EUR_ULPS, EQUITY_TOKENS_PER_SHARE);
    }

    //
    // Implements IContractId
    //

    function contractId() public pure returns (bytes32 id, uint256 version) {
        return (0x591e791aab2b14c80194b729a2abcba3e8cce1918be4061be170e7223357ae5c, 1);
    }
}

contract IsContract {

    ////////////////////////
    // Internal functions
    ////////////////////////

    function isContract(address addr)
        internal
        constant
        returns (bool)
    {
        uint256 size;
        // takes 700 gas
        assembly { size := extcodesize(addr) }
        return size > 0;
    }
}

// version history as per contractId
// 0 - initial version
// 1 - all ETO related terms dropped, fee disbursal recycle time added
// 2 - method to calculate amount before token fee added

/// @title sets terms of Platform
contract PlatformTerms is Math, IContractId {

    ////////////////////////
    // Constants
    ////////////////////////

    // fraction of fee deduced on successful ETO (see Math.sol for fraction definition)
    uint256 public constant PLATFORM_FEE_FRACTION = 3 * 10**16;
    // fraction of tokens deduced on succesful ETO
    uint256 public constant TOKEN_PARTICIPATION_FEE_FRACTION = 2 * 10**16;
    // share of Neumark reward platform operator gets
    // actually this is a divisor that splits Neumark reward in two parts
    // the results of division belongs to platform operator, the remaining reward part belongs to investor
    uint256 public constant PLATFORM_NEUMARK_SHARE = 2; // 50:50 division
    // ICBM investors whitelisted by default
    bool public constant IS_ICBM_INVESTOR_WHITELISTED = true;

    // token rate expires after
    uint256 public constant TOKEN_RATE_EXPIRES_AFTER = 4 hours;

    // time after which claimable tokens become recycleable in fee disbursal pool
    uint256 public constant DEFAULT_DISBURSAL_RECYCLE_AFTER_DURATION = 4 * 365 days;

    ////////////////////////
    // Public Function
    ////////////////////////

    // calculates investor's and platform operator's neumarks from total reward
    function calculateNeumarkDistribution(uint256 rewardNmk)
        public
        pure
        returns (uint256 platformNmk, uint256 investorNmk)
    {
        // round down - platform may get 1 wei less than investor
        platformNmk = rewardNmk / PLATFORM_NEUMARK_SHARE;
        // rewardNmk > platformNmk always
        return (platformNmk, rewardNmk - platformNmk);
    }

    // please note that this function and it's reverse calculateAmountWithoutFee will not produce exact reverse
    // values in each case due to rounding and that happens in cycle mod 51 for increasing values of tokenAmountWithFee
    // (frankly I'm not sure there are no more longer cycles, nothing in 50*51 cycle for sure which we checked)
    // so never rely in that in your code!
    // see ETOCommitment::onSigningTransition for example where it could lead to disastrous consequences
    function calculatePlatformTokenFee(uint256 tokenAmount)
        public
        pure
        returns (uint256)
    {
        // mind tokens having 0 precision
        // x*0.02 == x/50
        return divRound(tokenAmount, 50);
    }

    // this calculates the amount before fee from the amount that already includes token fee
    function calculateAmountWithoutFee(uint256 tokenAmountWithFee)
        public
        pure
        returns (uint256)
    {
        // x + 0.02x = tokenAmount, x = tokenAmount * 1/1.02 = tokenAmount * 50 / 51
        return divRound(mul(tokenAmountWithFee, 50), 51);
    }

    function calculatePlatformFee(uint256 amount)
        public
        pure
        returns (uint256)
    {
        return decimalFraction(amount, PLATFORM_FEE_FRACTION);
    }

    //
    // Implements IContractId
    //

    function contractId() public pure returns (bytes32 id, uint256 version) {
        return (0x95482babc4e32de6c4dc3910ee7ae62c8e427efde6bc4e9ce0d6d93e24c39323, 2);
    }
}

contract IBasicToken {

    ////////////////////////
    // Events
    ////////////////////////

    event Transfer(
        address indexed from,
        address indexed to,
        uint256 amount
    );

    ////////////////////////
    // Public functions
    ////////////////////////

    /// @dev This function makes it easy to get the total number of tokens
    /// @return The total number of tokens
    function totalSupply()
        public
        constant
        returns (uint256);

    /// @param owner The address that's balance is being requested
    /// @return The balance of `owner` at the current block
    function balanceOf(address owner)
        public
        constant
        returns (uint256 balance);

    /// @notice Send `amount` tokens to `to` from `msg.sender`
    /// @param to The address of the recipient
    /// @param amount The amount of tokens to be transferred
    /// @return Whether the transfer was successful or not
    function transfer(address to, uint256 amount)
        public
        returns (bool success);

}

/// @title allows deriving contract to recover any token or ether that it has balance of
/// @notice note that this opens your contracts to claims from various people saying they lost tokens and they want them back
///     be ready to handle such claims
/// @dev use with care!
///     1. ROLE_RECLAIMER is allowed to claim tokens, it's not returning tokens to original owner
///     2. in derived contract that holds any token by design you must override `reclaim` and block such possibility.
///         see ICBMLockedAccount as an example
contract Reclaimable is AccessControlled, AccessRoles {

    ////////////////////////
    // Constants
    ////////////////////////

    IBasicToken constant internal RECLAIM_ETHER = IBasicToken(0x0);

    ////////////////////////
    // Public functions
    ////////////////////////

    function reclaim(IBasicToken token)
        public
        only(ROLE_RECLAIMER)
    {
        address reclaimer = msg.sender;
        if(token == RECLAIM_ETHER) {
            reclaimer.transfer(address(this).balance);
        } else {
            uint256 balance = token.balanceOf(this);
            require(token.transfer(reclaimer, balance));
        }
    }
}

/// @title Abstracts snapshot id creation logics
/// @dev Mixin (internal interface) of the snapshot policy which abstracts snapshot id creation logics from Snapshot contract
/// @dev to be implemented and such implementation should be mixed with Snapshot-derived contract, see EveryBlock for simplest example of implementation and StandardSnapshotToken
contract MSnapshotPolicy {

    ////////////////////////
    // Internal functions
    ////////////////////////

    // The snapshot Ids need to be strictly increasing.
    // Whenever the snaspshot id changes, a new snapshot will be created.
    // As long as the same snapshot id is being returned, last snapshot will be updated as this indicates that snapshot id didn't change
    //
    // Values passed to `hasValueAt` and `valuteAt` are required
    // to be less or equal to `mCurrentSnapshotId()`.
    function mAdvanceSnapshotId()
        internal
        returns (uint256);

    // this is a version of mAdvanceSnapshotId that does not modify state but MUST return the same value
    // it is required to implement ITokenSnapshots interface cleanly
    function mCurrentSnapshotId()
        internal
        constant
        returns (uint256);

}

/// @title creates new snapshot id on each day boundary
/// @dev snapshot id is unix timestamp of current day boundary
contract Daily is MSnapshotPolicy {

    ////////////////////////
    // Constants
    ////////////////////////

    // Floor[2**128 / 1 days]
    uint256 private MAX_TIMESTAMP = 3938453320844195178974243141571391;

    ////////////////////////
    // Constructor
    ////////////////////////

    /// @param start snapshotId from which to start generating values, used to prevent cloning from incompatible schemes
    /// @dev start must be for the same day or 0, required for token cloning
    constructor(uint256 start) internal {
        // 0 is invalid value as we are past unix epoch
        if (start > 0) {
            uint256 base = dayBase(uint128(block.timestamp));
            // must be within current day base
            require(start >= base);
            // dayBase + 2**128 will not overflow as it is based on block.timestamp
            require(start < base + 2**128);
        }
    }

    ////////////////////////
    // Public functions
    ////////////////////////

    function snapshotAt(uint256 timestamp)
        public
        constant
        returns (uint256)
    {
        require(timestamp < MAX_TIMESTAMP);

        return dayBase(uint128(timestamp));
    }

    ////////////////////////
    // Internal functions
    ////////////////////////

    //
    // Implements MSnapshotPolicy
    //

    function mAdvanceSnapshotId()
        internal
        returns (uint256)
    {
        return mCurrentSnapshotId();
    }

    function mCurrentSnapshotId()
        internal
        constant
        returns (uint256)
    {
        // disregard overflows on block.timestamp, see MAX_TIMESTAMP
        return dayBase(uint128(block.timestamp));
    }

    function dayBase(uint128 timestamp)
        internal
        pure
        returns (uint256)
    {
        // Round down to the start of the day (00:00 UTC) and place in higher 128bits
        return 2**128 * (uint256(timestamp) / 1 days);
    }
}

contract ITokenMetadata {

    ////////////////////////
    // Public functions
    ////////////////////////

    function symbol()
        public
        constant
        returns (string);

    function name()
        public
        constant
        returns (string);

    function decimals()
        public
        constant
        returns (uint8);
}

/// @title adds token metadata to token contract
/// @dev see Neumark for example implementation
contract TokenMetadata is ITokenMetadata {

    ////////////////////////
    // Immutable state
    ////////////////////////

    // The Token's name: e.g. DigixDAO Tokens
    string private NAME;

    // An identifier: e.g. REP
    string private SYMBOL;

    // Number of decimals of the smallest unit
    uint8 private DECIMALS;

    // An arbitrary versioning scheme
    string private VERSION;

    ////////////////////////
    // Constructor
    ////////////////////////

    /// @notice Constructor to set metadata
    /// @param tokenName Name of the new token
    /// @param decimalUnits Number of decimals of the new token
    /// @param tokenSymbol Token Symbol for the new token
    /// @param version Token version ie. when cloning is used
    constructor(
        string tokenName,
        uint8 decimalUnits,
        string tokenSymbol,
        string version
    )
        public
    {
        NAME = tokenName;                                 // Set the name
        SYMBOL = tokenSymbol;                             // Set the symbol
        DECIMALS = decimalUnits;                          // Set the decimals
        VERSION = version;
    }

    ////////////////////////
    // Public functions
    ////////////////////////

    function name()
        public
        constant
        returns (string)
    {
        return NAME;
    }

    function symbol()
        public
        constant
        returns (string)
    {
        return SYMBOL;
    }

    function decimals()
        public
        constant
        returns (uint8)
    {
        return DECIMALS;
    }

    function version()
        public
        constant
        returns (string)
    {
        return VERSION;
    }
}

contract IERC20Allowance {

    ////////////////////////
    // Events
    ////////////////////////

    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 amount
    );

    ////////////////////////
    // Public functions
    ////////////////////////

    /// @dev This function makes it easy to read the `allowed[]` map
    /// @param owner The address of the account that owns the token
    /// @param spender The address of the account able to transfer the tokens
    /// @return Amount of remaining tokens of owner that spender is allowed
    ///  to spend
    function allowance(address owner, address spender)
        public
        constant
        returns (uint256 remaining);

    /// @notice `msg.sender` approves `spender` to spend `amount` tokens on
    ///  its behalf. This is a modified version of the ERC20 approve function
    ///  to be a little bit safer
    /// @param spender The address of the account able to transfer the tokens
    /// @param amount The amount of tokens to be approved for transfer
    /// @return True if the approval was successful
    function approve(address spender, uint256 amount)
        public
        returns (bool success);

    /// @notice Send `amount` tokens to `to` from `from` on the condition it
    ///  is approved by `from`
    /// @param from The address holding the tokens being transferred
    /// @param to The address of the recipient
    /// @param amount The amount of tokens to be transferred
    /// @return True if the transfer was successful
    function transferFrom(address from, address to, uint256 amount)
        public
        returns (bool success);

}

contract IERC20Token is IBasicToken, IERC20Allowance {

}

/// @title controls spending approvals
/// @dev TokenAllowance observes this interface, Neumark contract implements it
contract MTokenAllowanceController {

    ////////////////////////
    // Internal functions
    ////////////////////////

    /// @notice Notifies the controller about an approval allowing the
    ///  controller to react if desired
    /// @param owner The address that calls `approve()`
    /// @param spender The spender in the `approve()` call
    /// @param amount The amount in the `approve()` call
    /// @return False if the controller does not authorize the approval
    function mOnApprove(
        address owner,
        address spender,
        uint256 amount
    )
        internal
        returns (bool allow);

    /// @notice Allows to override allowance approved by the owner
    ///         Primary role is to enable forced transfers, do not override if you do not like it
    ///         Following behavior is expected in the observer
    ///         approve() - should revert if mAllowanceOverride() > 0
    ///         allowance() - should return mAllowanceOverride() if set
    ///         transferFrom() - should override allowance if mAllowanceOverride() > 0
    /// @param owner An address giving allowance to spender
    /// @param spender An address getting  a right to transfer allowance amount from the owner
    /// @return current allowance amount
    function mAllowanceOverride(
        address owner,
        address spender
    )
        internal
        constant
        returns (uint256 allowance);
}

/// @title controls token transfers
/// @dev BasicSnapshotToken observes this interface, Neumark contract implements it
contract MTokenTransferController {

    ////////////////////////
    // Internal functions
    ////////////////////////

    /// @notice Notifies the controller about a token transfer allowing the
    ///  controller to react if desired
    /// @param from The origin of the transfer
    /// @param to The destination of the transfer
    /// @param amount The amount of the transfer
    /// @return False if the controller does not authorize the transfer
    function mOnTransfer(
        address from,
        address to,
        uint256 amount
    )
        internal
        returns (bool allow);

}

/// @title controls approvals and transfers
/// @dev The token controller contract must implement these functions, see Neumark as example
/// @dev please note that controller may be a separate contract that is called from mOnTransfer and mOnApprove functions
contract MTokenController is MTokenTransferController, MTokenAllowanceController {
}

/// @title internal token transfer function
/// @dev see BasicSnapshotToken for implementation
contract MTokenTransfer {

    ////////////////////////
    // Internal functions
    ////////////////////////

    /// @dev This is the actual transfer function in the token contract, it can
    ///  only be called by other functions in this contract.
    /// @param from The address holding the tokens being transferred
    /// @param to The address of the recipient
    /// @param amount The amount of tokens to be transferred
    /// @dev  reverts if transfer was not successful
    function mTransfer(
        address from,
        address to,
        uint256 amount
    )
        internal;
}

contract IERC677Callback {

    ////////////////////////
    // Public functions
    ////////////////////////

    // NOTE: This call can be initiated by anyone. You need to make sure that
    // it is send by the token (`require(msg.sender == token)`) or make sure
    // amount is valid (`require(token.allowance(this) >= amount)`).
    function receiveApproval(
        address from,
        uint256 amount,
        address token, // IERC667Token
        bytes data
    )
        public
        returns (bool success);

}

contract IERC677Allowance is IERC20Allowance {

    ////////////////////////
    // Public functions
    ////////////////////////

    /// @notice `msg.sender` approves `spender` to send `amount` tokens on
    ///  its behalf, and then a function is triggered in the contract that is
    ///  being approved, `spender`. This allows users to use their tokens to
    ///  interact with contracts in one function call instead of two
    /// @param spender The address of the contract able to transfer the tokens
    /// @param amount The amount of tokens to be approved for transfer
    /// @return True if the function call was successful
    function approveAndCall(address spender, uint256 amount, bytes extraData)
        public
        returns (bool success);

}

contract IERC677Token is IERC20Token, IERC677Allowance {
}

/// @title token spending approval and transfer
/// @dev implements token approval and transfers and exposes relevant part of ERC20 and ERC677 approveAndCall
///     may be mixed in with any basic token (implementing mTransfer) like BasicSnapshotToken or MintableSnapshotToken to add approval mechanism
///     observes MTokenAllowanceController interface
///     observes MTokenTransfer
contract TokenAllowance is
    MTokenTransfer,
    MTokenAllowanceController,
    IERC20Allowance,
    IERC677Token
{

    ////////////////////////
    // Mutable state
    ////////////////////////

    // `allowed` tracks rights to spends others tokens as per ERC20
    // owner => spender => amount
    mapping (address => mapping (address => uint256)) private _allowed;

    ////////////////////////
    // Constructor
    ////////////////////////

    constructor()
        internal
    {
    }

    ////////////////////////
    // Public functions
    ////////////////////////

    //
    // Implements IERC20Token
    //

    /// @dev This function makes it easy to read the `allowed[]` map
    /// @param owner The address of the account that owns the token
    /// @param spender The address of the account able to transfer the tokens
    /// @return Amount of remaining tokens of _owner that _spender is allowed
    ///  to spend
    function allowance(address owner, address spender)
        public
        constant
        returns (uint256 remaining)
    {
        uint256 override = mAllowanceOverride(owner, spender);
        if (override > 0) {
            return override;
        }
        return _allowed[owner][spender];
    }

    /// @notice `msg.sender` approves `_spender` to spend `_amount` tokens on
    ///  its behalf. This is a modified version of the ERC20 approve function
    ///  where allowance per spender must be 0 to allow change of such allowance
    /// @param spender The address of the account able to transfer the tokens
    /// @param amount The amount of tokens to be approved for transfer
    /// @return True or reverts, False is never returned
    function approve(address spender, uint256 amount)
        public
        returns (bool success)
    {
        // Alerts the token controller of the approve function call
        require(mOnApprove(msg.sender, spender, amount));

        // To change the approve amount you first have to reduce the addresses`
        //  allowance to zero by calling `approve(_spender,0)` if it is not
        //  already 0 to mitigate the race condition described here:
        //  https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
        require((amount == 0 || _allowed[msg.sender][spender] == 0) && mAllowanceOverride(msg.sender, spender) == 0);

        _allowed[msg.sender][spender] = amount;
        emit Approval(msg.sender, spender, amount);
        return true;
    }

    /// @notice Send `_amount` tokens to `_to` from `_from` on the condition it
    ///  is approved by `_from`
    /// @param from The address holding the tokens being transferred
    /// @param to The address of the recipient
    /// @param amount The amount of tokens to be transferred
    /// @return True if the transfer was successful, reverts in any other case
    function transferFrom(address from, address to, uint256 amount)
        public
        returns (bool success)
    {
        uint256 allowed = mAllowanceOverride(from, msg.sender);
        if (allowed == 0) {
            // The standard ERC 20 transferFrom functionality
            allowed = _allowed[from][msg.sender];
            // yes this will underflow but then we'll revert. will cost gas however so don't underflow
            _allowed[from][msg.sender] -= amount;
        }
        require(allowed >= amount);
        mTransfer(from, to, amount);
        return true;
    }

    //
    // Implements IERC677Token
    //

    /// @notice `msg.sender` approves `_spender` to send `_amount` tokens on
    ///  its behalf, and then a function is triggered in the contract that is
    ///  being approved, `_spender`. This allows users to use their tokens to
    ///  interact with contracts in one function call instead of two
    /// @param spender The address of the contract able to transfer the tokens
    /// @param amount The amount of tokens to be approved for transfer
    /// @return True or reverts, False is never returned
    function approveAndCall(
        address spender,
        uint256 amount,
        bytes extraData
    )
        public
        returns (bool success)
    {
        require(approve(spender, amount));

        success = IERC677Callback(spender).receiveApproval(
            msg.sender,
            amount,
            this,
            extraData
        );
        require(success);

        return true;
    }

    ////////////////////////
    // Internal functions
    ////////////////////////

    //
    // Implements default MTokenAllowanceController
    //

    // no override in default implementation
    function mAllowanceOverride(
        address /*owner*/,
        address /*spender*/
    )
        internal
        constant
        returns (uint256)
    {
        return 0;
    }
}

/// @title Reads and writes snapshots
/// @dev Manages reading and writing a series of values, where each value has assigned a snapshot id for access to historical data
/// @dev may be added to any contract to provide snapshotting mechanism. should be mixed in with any of MSnapshotPolicy implementations to customize snapshot creation mechanics
///     observes MSnapshotPolicy
/// based on MiniMe token
contract Snapshot is MSnapshotPolicy {

    ////////////////////////
    // Types
    ////////////////////////

    /// @dev `Values` is the structure that attaches a snapshot id to a
    ///  given value, the snapshot id attached is the one that last changed the
    ///  value
    struct Values {

        // `snapshotId` is the snapshot id that the value was generated at
        uint256 snapshotId;

        // `value` at a specific snapshot id
        uint256 value;
    }

    ////////////////////////
    // Internal functions
    ////////////////////////

    function hasValue(
        Values[] storage values
    )
        internal
        constant
        returns (bool)
    {
        return values.length > 0;
    }

    /// @dev makes sure that 'snapshotId' between current snapshot id (mCurrentSnapshotId) and first snapshot id. this guarantees that getValueAt returns value from one of the snapshots.
    function hasValueAt(
        Values[] storage values,
        uint256 snapshotId
    )
        internal
        constant
        returns (bool)
    {
        require(snapshotId <= mCurrentSnapshotId());
        return values.length > 0 && values[0].snapshotId <= snapshotId;
    }

    /// gets last value in the series
    function getValue(
        Values[] storage values,
        uint256 defaultValue
    )
        internal
        constant
        returns (uint256)
    {
        if (values.length == 0) {
            return defaultValue;
        } else {
            uint256 last = values.length - 1;
            return values[last].value;
        }
    }

    /// @dev `getValueAt` retrieves value at a given snapshot id
    /// @param values The series of values being queried
    /// @param snapshotId Snapshot id to retrieve the value at
    /// @return Value in series being queried
    function getValueAt(
        Values[] storage values,
        uint256 snapshotId,
        uint256 defaultValue
    )
        internal
        constant
        returns (uint256)
    {
        require(snapshotId <= mCurrentSnapshotId());

        // Empty value
        if (values.length == 0) {
            return defaultValue;
        }

        // Shortcut for the out of bounds snapshots
        uint256 last = values.length - 1;
        uint256 lastSnapshot = values[last].snapshotId;
        if (snapshotId >= lastSnapshot) {
            return values[last].value;
        }
        uint256 firstSnapshot = values[0].snapshotId;
        if (snapshotId < firstSnapshot) {
            return defaultValue;
        }
        // Binary search of the value in the array
        uint256 min = 0;
        uint256 max = last;
        while (max > min) {
            uint256 mid = (max + min + 1) / 2;
            // must always return lower indice for approximate searches
            if (values[mid].snapshotId <= snapshotId) {
                min = mid;
            } else {
                max = mid - 1;
            }
        }
        return values[min].value;
    }

    /// @dev `setValue` used to update sequence at next snapshot
    /// @param values The sequence being updated
    /// @param value The new last value of sequence
    function setValue(
        Values[] storage values,
        uint256 value
    )
        internal
    {
        // TODO: simplify or break into smaller functions

        uint256 currentSnapshotId = mAdvanceSnapshotId();
        // Always create a new entry if there currently is no value
        bool empty = values.length == 0;
        if (empty) {
            // Create a new entry
            values.push(
                Values({
                    snapshotId: currentSnapshotId,
                    value: value
                })
            );
            return;
        }

        uint256 last = values.length - 1;
        bool hasNewSnapshot = values[last].snapshotId < currentSnapshotId;
        if (hasNewSnapshot) {

            // Do nothing if the value was not modified
            bool unmodified = values[last].value == value;
            if (unmodified) {
                return;
            }

            // Create new entry
            values.push(
                Values({
                    snapshotId: currentSnapshotId,
                    value: value
                })
            );
        } else {

            // We are updating the currentSnapshotId
            bool previousUnmodified = last > 0 && values[last - 1].value == value;
            if (previousUnmodified) {
                // Remove current snapshot if current value was set to previous value
                delete values[last];
                values.length--;
                return;
            }

            // Overwrite next snapshot entry
            values[last].value = value;
        }
    }
}

/// @title access to snapshots of a token
/// @notice allows to implement complex token holder rights like revenue disbursal or voting
/// @notice snapshots are series of values with assigned ids. ids increase strictly. particular id mechanism is not assumed
contract ITokenSnapshots {

    ////////////////////////
    // Public functions
    ////////////////////////

    /// @notice Total amount of tokens at a specific `snapshotId`.
    /// @param snapshotId of snapshot at which totalSupply is queried
    /// @return The total amount of tokens at `snapshotId`
    /// @dev reverts on snapshotIds greater than currentSnapshotId()
    /// @dev returns 0 for snapshotIds less than snapshotId of first value
    function totalSupplyAt(uint256 snapshotId)
        public
        constant
        returns(uint256);

    /// @dev Queries the balance of `owner` at a specific `snapshotId`
    /// @param owner The address from which the balance will be retrieved
    /// @param snapshotId of snapshot at which the balance is queried
    /// @return The balance at `snapshotId`
    function balanceOfAt(address owner, uint256 snapshotId)
        public
        constant
        returns (uint256);

    /// @notice upper bound of series of snapshotIds for which there's a value in series
    /// @return snapshotId
    function currentSnapshotId()
        public
        constant
        returns (uint256);
}

/// @title represents link between cloned and parent token
/// @dev when token is clone from other token, initial balances of the cloned token
///     correspond to balances of parent token at the moment of parent snapshot id specified
/// @notice please note that other tokens beside snapshot token may be cloned
contract IClonedTokenParent is ITokenSnapshots {

    ////////////////////////
    // Public functions
    ////////////////////////


    /// @return address of parent token, address(0) if root
    /// @dev parent token does not need to clonable, nor snapshottable, just a normal token
    function parentToken()
        public
        constant
        returns(IClonedTokenParent parent);

    /// @return snapshot at wchich initial token distribution was taken
    function parentSnapshotId()
        public
        constant
        returns(uint256 snapshotId);
}

/// @title token with snapshots and transfer functionality
/// @dev observes MTokenTransferController interface
///     observes ISnapshotToken interface
///     implementes MTokenTransfer interface
contract BasicSnapshotToken is
    MTokenTransfer,
    MTokenTransferController,
    IClonedTokenParent,
    IBasicToken,
    Snapshot
{
    ////////////////////////
    // Immutable state
    ////////////////////////

    // `PARENT_TOKEN` is the Token address that was cloned to produce this token;
    //  it will be 0x0 for a token that was not cloned
    IClonedTokenParent private PARENT_TOKEN;

    // `PARENT_SNAPSHOT_ID` is the snapshot id from the Parent Token that was
    //  used to determine the initial distribution of the cloned token
    uint256 private PARENT_SNAPSHOT_ID;

    ////////////////////////
    // Mutable state
    ////////////////////////

    // `balances` is the map that tracks the balance of each address, in this
    //  contract when the balance changes the snapshot id that the change
    //  occurred is also included in the map
    mapping (address => Values[]) internal _balances;

    // Tracks the history of the `totalSupply` of the token
    Values[] internal _totalSupplyValues;

    ////////////////////////
    // Constructor
    ////////////////////////

    /// @notice Constructor to create snapshot token
    /// @param parentToken Address of the parent token, set to 0x0 if it is a
    ///  new token
    /// @param parentSnapshotId at which snapshot id clone was created, set to 0 to clone at upper bound
    /// @dev please not that as long as cloned token does not overwrite value at current snapshot id, it will refer
    ///     to parent token at which this snapshot still may change until snapshot id increases. for that time tokens are coupled
    ///     this is prevented by parentSnapshotId value of parentToken.currentSnapshotId() - 1 being the maxiumum
    ///     see SnapshotToken.js test to learn consequences coupling has.
    constructor(
        IClonedTokenParent parentToken,
        uint256 parentSnapshotId
    )
        Snapshot()
        internal
    {
        PARENT_TOKEN = parentToken;
        if (parentToken == address(0)) {
            require(parentSnapshotId == 0);
        } else {
            if (parentSnapshotId == 0) {
                require(parentToken.currentSnapshotId() > 0);
                PARENT_SNAPSHOT_ID = parentToken.currentSnapshotId() - 1;
            } else {
                PARENT_SNAPSHOT_ID = parentSnapshotId;
            }
        }
    }

    ////////////////////////
    // Public functions
    ////////////////////////

    //
    // Implements IBasicToken
    //

    /// @dev This function makes it easy to get the total number of tokens
    /// @return The total number of tokens
    function totalSupply()
        public
        constant
        returns (uint256)
    {
        return totalSupplyAtInternal(mCurrentSnapshotId());
    }

    /// @param owner The address that's balance is being requested
    /// @return The balance of `owner` at the current block
    function balanceOf(address owner)
        public
        constant
        returns (uint256 balance)
    {
        return balanceOfAtInternal(owner, mCurrentSnapshotId());
    }

    /// @notice Send `amount` tokens to `to` from `msg.sender`
    /// @param to The address of the recipient
    /// @param amount The amount of tokens to be transferred
    /// @return True if the transfer was successful, reverts in any other case
    function transfer(address to, uint256 amount)
        public
        returns (bool success)
    {
        mTransfer(msg.sender, to, amount);
        return true;
    }

    //
    // Implements ITokenSnapshots
    //

    function totalSupplyAt(uint256 snapshotId)
        public
        constant
        returns(uint256)
    {
        return totalSupplyAtInternal(snapshotId);
    }

    function balanceOfAt(address owner, uint256 snapshotId)
        public
        constant
        returns (uint256)
    {
        return balanceOfAtInternal(owner, snapshotId);
    }

    function currentSnapshotId()
        public
        constant
        returns (uint256)
    {
        return mCurrentSnapshotId();
    }

    //
    // Implements IClonedTokenParent
    //

    function parentToken()
        public
        constant
        returns(IClonedTokenParent parent)
    {
        return PARENT_TOKEN;
    }

    /// @return snapshot at wchich initial token distribution was taken
    function parentSnapshotId()
        public
        constant
        returns(uint256 snapshotId)
    {
        return PARENT_SNAPSHOT_ID;
    }

    //
    // Other public functions
    //

    /// @notice gets all token balances of 'owner'
    /// @dev intended to be called via eth_call where gas limit is not an issue
    function allBalancesOf(address owner)
        external
        constant
        returns (uint256[2][])
    {
        /* very nice and working implementation below,
        // copy to memory
        Values[] memory values = _balances[owner];
        do assembly {
            // in memory structs have simple layout where every item occupies uint256
            balances := values
        } while (false);*/

        Values[] storage values = _balances[owner];
        uint256[2][] memory balances = new uint256[2][](values.length);
        for(uint256 ii = 0; ii < values.length; ++ii) {
            balances[ii] = [values[ii].snapshotId, values[ii].value];
        }

        return balances;
    }

    ////////////////////////
    // Internal functions
    ////////////////////////

    function totalSupplyAtInternal(uint256 snapshotId)
        internal
        constant
        returns(uint256)
    {
        Values[] storage values = _totalSupplyValues;

        // If there is a value, return it, reverts if value is in the future
        if (hasValueAt(values, snapshotId)) {
            return getValueAt(values, snapshotId, 0);
        }

        // Try parent contract at or before the fork
        if (address(PARENT_TOKEN) != 0) {
            uint256 earlierSnapshotId = PARENT_SNAPSHOT_ID > snapshotId ? snapshotId : PARENT_SNAPSHOT_ID;
            return PARENT_TOKEN.totalSupplyAt(earlierSnapshotId);
        }

        // Default to an empty balance
        return 0;
    }

    // get balance at snapshot if with continuation in parent token
    function balanceOfAtInternal(address owner, uint256 snapshotId)
        internal
        constant
        returns (uint256)
    {
        Values[] storage values = _balances[owner];

        // If there is a value, return it, reverts if value is in the future
        if (hasValueAt(values, snapshotId)) {
            return getValueAt(values, snapshotId, 0);
        }

        // Try parent contract at or before the fork
        if (PARENT_TOKEN != address(0)) {
            uint256 earlierSnapshotId = PARENT_SNAPSHOT_ID > snapshotId ? snapshotId : PARENT_SNAPSHOT_ID;
            return PARENT_TOKEN.balanceOfAt(owner, earlierSnapshotId);
        }

        // Default to an empty balance
        return 0;
    }

    //
    // Implements MTokenTransfer
    //

    /// @dev This is the actual transfer function in the token contract, it can
    ///  only be called by other functions in this contract.
    /// @param from The address holding the tokens being transferred
    /// @param to The address of the recipient
    /// @param amount The amount of tokens to be transferred
    /// @return True if the transfer was successful, reverts in any other case
    function mTransfer(
        address from,
        address to,
        uint256 amount
    )
        internal
    {
        // never send to address 0
        require(to != address(0));
        // block transfers in clone that points to future/current snapshots of parent token
        require(parentToken() == address(0) || parentSnapshotId() < parentToken().currentSnapshotId());
        // Alerts the token controller of the transfer
        require(mOnTransfer(from, to, amount));

        // If the amount being transfered is more than the balance of the
        //  account the transfer reverts
        uint256 previousBalanceFrom = balanceOf(from);
        require(previousBalanceFrom >= amount);

        // First update the balance array with the new value for the address
        //  sending the tokens
        uint256 newBalanceFrom = previousBalanceFrom - amount;
        setValue(_balances[from], newBalanceFrom);

        // Then update the balance array with the new value for the address
        //  receiving the tokens
        uint256 previousBalanceTo = balanceOf(to);
        uint256 newBalanceTo = previousBalanceTo + amount;
        assert(newBalanceTo >= previousBalanceTo); // Check for overflow
        setValue(_balances[to], newBalanceTo);

        // An event to make the transfer easy to find on the blockchain
        emit Transfer(from, to, amount);
    }
}

/// @title token generation and destruction
/// @dev internal interface providing token generation and destruction, see MintableSnapshotToken for implementation
contract MTokenMint {

    ////////////////////////
    // Internal functions
    ////////////////////////

    /// @notice Generates `amount` tokens that are assigned to `owner`
    /// @param owner The address that will be assigned the new tokens
    /// @param amount The quantity of tokens generated
    /// @dev reverts if tokens could not be generated
    function mGenerateTokens(address owner, uint256 amount)
        internal;

    /// @notice Burns `amount` tokens from `owner`
    /// @param owner The address that will lose the tokens
    /// @param amount The quantity of tokens to burn
    /// @dev reverts if tokens could not be destroyed
    function mDestroyTokens(address owner, uint256 amount)
        internal;
}

/// @title basic snapshot token with facitilites to generate and destroy tokens
/// @dev implementes MTokenMint, does not expose any public functions that create/destroy tokens
contract MintableSnapshotToken is
    BasicSnapshotToken,
    MTokenMint
{

    ////////////////////////
    // Constructor
    ////////////////////////

    /// @notice Constructor to create a MintableSnapshotToken
    /// @param parentToken Address of the parent token, set to 0x0 if it is a
    ///  new token
    constructor(
        IClonedTokenParent parentToken,
        uint256 parentSnapshotId
    )
        BasicSnapshotToken(parentToken, parentSnapshotId)
        internal
    {}

    /// @notice Generates `amount` tokens that are assigned to `owner`
    /// @param owner The address that will be assigned the new tokens
    /// @param amount The quantity of tokens generated
    function mGenerateTokens(address owner, uint256 amount)
        internal
    {
        // never create for address 0
        require(owner != address(0));
        // block changes in clone that points to future/current snapshots of patent token
        require(parentToken() == address(0) || parentSnapshotId() < parentToken().currentSnapshotId());

        uint256 curTotalSupply = totalSupply();
        uint256 newTotalSupply = curTotalSupply + amount;
        require(newTotalSupply >= curTotalSupply); // Check for overflow

        uint256 previousBalanceTo = balanceOf(owner);
        uint256 newBalanceTo = previousBalanceTo + amount;
        assert(newBalanceTo >= previousBalanceTo); // Check for overflow

        setValue(_totalSupplyValues, newTotalSupply);
        setValue(_balances[owner], newBalanceTo);

        emit Transfer(0, owner, amount);
    }

    /// @notice Burns `amount` tokens from `owner`
    /// @param owner The address that will lose the tokens
    /// @param amount The quantity of tokens to burn
    function mDestroyTokens(address owner, uint256 amount)
        internal
    {
        // block changes in clone that points to future/current snapshots of patent token
        require(parentToken() == address(0) || parentSnapshotId() < parentToken().currentSnapshotId());

        uint256 curTotalSupply = totalSupply();
        require(curTotalSupply >= amount);

        uint256 previousBalanceFrom = balanceOf(owner);
        require(previousBalanceFrom >= amount);

        uint256 newTotalSupply = curTotalSupply - amount;
        uint256 newBalanceFrom = previousBalanceFrom - amount;
        setValue(_totalSupplyValues, newTotalSupply);
        setValue(_balances[owner], newBalanceFrom);

        emit Transfer(owner, 0, amount);
    }
}

/*
    Copyright 2016, Jordi Baylina
    Copyright 2017, Remco Bloemen, Marcin Rudolf

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/// @title StandardSnapshotToken Contract
/// @author Jordi Baylina, Remco Bloemen, Marcin Rudolf
/// @dev This token contract's goal is to make it easy for anyone to clone this
///  token using the token distribution at a given block, this will allow DAO's
///  and DApps to upgrade their features in a decentralized manner without
///  affecting the original token
/// @dev It is ERC20 compliant, but still needs to under go further testing.
/// @dev Various contracts are composed to provide required functionality of this token, different compositions are possible
///     MintableSnapshotToken provides transfer, miniting and snapshotting functions
///     TokenAllowance provides approve/transferFrom functions
///     TokenMetadata adds name, symbol and other token metadata
/// @dev This token is still abstract, Snapshot, BasicSnapshotToken and TokenAllowance observe interfaces that must be implemented
///     MSnapshotPolicy - particular snapshot id creation mechanism
///     MTokenController - controlls approvals and transfers
///     see Neumark as an example
/// @dev implements ERC223 token transfer
contract StandardSnapshotToken is
    MintableSnapshotToken,
    TokenAllowance
{
    ////////////////////////
    // Constructor
    ////////////////////////

    /// @notice Constructor to create a MiniMeToken
    ///  is a new token
    /// param tokenName Name of the new token
    /// param decimalUnits Number of decimals of the new token
    /// param tokenSymbol Token Symbol for the new token
    constructor(
        IClonedTokenParent parentToken,
        uint256 parentSnapshotId
    )
        MintableSnapshotToken(parentToken, parentSnapshotId)
        TokenAllowance()
        internal
    {}
}

/// @title current ERC223 fallback function
/// @dev to be used in all future token contract
/// @dev NEU and ICBMEtherToken (obsolete) are the only contracts that still uses IERC223LegacyCallback
contract IERC223Callback {

    ////////////////////////
    // Public functions
    ////////////////////////

    function tokenFallback(address from, uint256 amount, bytes data)
        public;

}

contract IERC223Token is IERC20Token, ITokenMetadata {

    /// @dev Departure: We do not log data, it has no advantage over a standard
    ///     log event. By sticking to the standard log event we
    ///     stay compatible with constracts that expect and ERC20 token.

    // event Transfer(
    //    address indexed from,
    //    address indexed to,
    //    uint256 amount,
    //    bytes data);


    /// @dev Departure: We do not use the callback on regular transfer calls to
    ///     stay compatible with constracts that expect and ERC20 token.

    // function transfer(address to, uint256 amount)
    //     public
    //     returns (bool);

    ////////////////////////
    // Public functions
    ////////////////////////

    function transfer(address to, uint256 amount, bytes data)
        public
        returns (bool);
}

/// @title describes layout of claims in 256bit records stored for identities
/// @dev intended to be derived by contracts requiring access to particular claims
contract IdentityRecord {

    ////////////////////////
    // Types
    ////////////////////////

    /// @dev here the idea is to have claims of size of uint256 and use this struct
    ///     to translate in and out of this struct. until we do not cross uint256 we
    ///     have binary compatibility
    struct IdentityClaims {
        bool isVerified; // 1 bit
        bool isSophisticatedInvestor; // 1 bit
        bool hasBankAccount; // 1 bit
        bool accountFrozen; // 1 bit
        bool requiresRegDAccreditation; // 1 bit
        bool hasValidRegDAccreditation; // 1 bit
        // uint250 reserved
    }

    ////////////////////////
    // Internal functions
    ////////////////////////

    /// translates uint256 to struct
    function deserializeClaims(bytes32 data) internal pure returns (IdentityClaims memory claims) {
        // for memory layout of struct, each field below word length occupies whole word
        // todo: shift to SHR instruction
        assembly {
            mstore(claims, and(data, 0x1))
            mstore(add(claims, 0x20), div(and(data, 0x2), 0x2))
            mstore(add(claims, 0x40), div(and(data, 0x4), 0x4))
            mstore(add(claims, 0x60), div(and(data, 0x8), 0x8))
            mstore(add(claims, 0x80), div(and(data, 0x10), 0x10))
            mstore(add(claims, 0xA0), div(and(data, 0x20), 0x20))
        }
    }
}


/// @title interface storing and retrieve 256bit claims records for identity
/// actual format of record is decoupled from storage (except maximum size)
contract IIdentityRegistry {

    ////////////////////////
    // Events
    ////////////////////////

    /// provides information on setting claims
    event LogSetClaims(
        address indexed identity,
        bytes32 oldClaims,
        bytes32 newClaims
    );

    ////////////////////////
    // Public functions
    ////////////////////////

    /// get claims for identity
    function getClaims(address identity) public constant returns (bytes32);

    /// set claims for identity
    /// @dev odlClaims and newClaims used for optimistic locking. to override with newClaims
    ///     current claims must be oldClaims
    function setClaims(address identity, bytes32 oldClaims, bytes32 newClaims) public;
}

/// @title known interfaces (services) of the platform
/// "known interface" is a unique id of service provided by the platform and discovered via Universe contract
///  it does not refer to particular contract/interface ABI, particular service may be delivered via different implementations
///  however for a few contracts we commit platform to particular implementation (all ICBM Contracts, Universe itself etc.)
/// @dev constants are kept in CODE not in STORAGE so they are comparatively cheap
contract KnownInterfaces {

    ////////////////////////
    // Constants
    ////////////////////////

    // NOTE: All interface are set to the keccak256 hash of the
    // CamelCased interface or singleton name, i.e.
    // KNOWN_INTERFACE_NEUMARK = keccak256("Neumark")

    // EIP 165 + EIP 820 should be use instead but it seems they are far from finished
    // also interface signature should be build automatically by solidity. otherwise it is a pure hassle

    // neumark token interface and sigleton keccak256("Neumark")
    bytes4 internal constant KNOWN_INTERFACE_NEUMARK = 0xeb41a1bd;

    // ether token interface and singleton keccak256("EtherToken")
    bytes4 internal constant KNOWN_INTERFACE_ETHER_TOKEN = 0x8cf73cf1;

    // euro token interface and singleton keccak256("EuroToken")
    bytes4 internal constant KNOWN_INTERFACE_EURO_TOKEN = 0x83c3790b;

    // euro token interface and singleton keccak256("EuroTokenController")
    bytes4 internal constant KNOWN_INTERFACE_EURO_TOKEN_CONTROLLER = 0x33ac4661;

    // identity registry interface and singleton keccak256("IIdentityRegistry")
    bytes4 internal constant KNOWN_INTERFACE_IDENTITY_REGISTRY = 0x0a72e073;

    // currency rates oracle interface and singleton keccak256("ITokenExchangeRateOracle")
    bytes4 internal constant KNOWN_INTERFACE_TOKEN_EXCHANGE_RATE_ORACLE = 0xc6e5349e;

    // fee disbursal interface and singleton keccak256("IFeeDisbursal")
    bytes4 internal constant KNOWN_INTERFACE_FEE_DISBURSAL = 0xf4c848e8;

    // platform portfolio holding equity tokens belonging to NEU holders keccak256("IPlatformPortfolio");
    bytes4 internal constant KNOWN_INTERFACE_PLATFORM_PORTFOLIO = 0xaa1590d0;

    // token exchange interface and singleton keccak256("ITokenExchange")
    bytes4 internal constant KNOWN_INTERFACE_TOKEN_EXCHANGE = 0xddd7a521;

    // service exchanging euro token for gas ("IGasTokenExchange")
    bytes4 internal constant KNOWN_INTERFACE_GAS_EXCHANGE = 0x89dbc6de;

    // access policy interface and singleton keccak256("IAccessPolicy")
    bytes4 internal constant KNOWN_INTERFACE_ACCESS_POLICY = 0xb05049d9;

    // euro lock account (upgraded) keccak256("LockedAccount:Euro")
    bytes4 internal constant KNOWN_INTERFACE_EURO_LOCK = 0x2347a19e;

    // ether lock account (upgraded) keccak256("LockedAccount:Ether")
    bytes4 internal constant KNOWN_INTERFACE_ETHER_LOCK = 0x978a6823;

    // icbm euro lock account keccak256("ICBMLockedAccount:Euro")
    bytes4 internal constant KNOWN_INTERFACE_ICBM_EURO_LOCK = 0x36021e14;

    // ether lock account (upgraded) keccak256("ICBMLockedAccount:Ether")
    bytes4 internal constant KNOWN_INTERFACE_ICBM_ETHER_LOCK = 0x0b58f006;

    // ether token interface and singleton keccak256("ICBMEtherToken")
    bytes4 internal constant KNOWN_INTERFACE_ICBM_ETHER_TOKEN = 0xae8b50b9;

    // euro token interface and singleton keccak256("ICBMEuroToken")
    bytes4 internal constant KNOWN_INTERFACE_ICBM_EURO_TOKEN = 0xc2c6cd72;

    // ICBM commitment interface interface and singleton keccak256("ICBMCommitment")
    bytes4 internal constant KNOWN_INTERFACE_ICBM_COMMITMENT = 0x7f2795ef;

    // ethereum fork arbiter interface and singleton keccak256("IEthereumForkArbiter")
    bytes4 internal constant KNOWN_INTERFACE_FORK_ARBITER = 0x2fe7778c;

    // Platform terms interface and singletong keccak256("PlatformTerms")
    bytes4 internal constant KNOWN_INTERFACE_PLATFORM_TERMS = 0x75ecd7f8;

    // for completness we define Universe service keccak256("Universe");
    bytes4 internal constant KNOWN_INTERFACE_UNIVERSE = 0xbf202454;

    // ETO commitment interface (collection) keccak256("ICommitment")
    bytes4 internal constant KNOWN_INTERFACE_COMMITMENT = 0xfa0e0c60;

    // Equity Token Controller interface (collection) keccak256("IEquityTokenController")
    bytes4 internal constant KNOWN_INTERFACE_EQUITY_TOKEN_CONTROLLER = 0xfa30b2f1;

    // Equity Token interface (collection) keccak256("IEquityToken")
    bytes4 internal constant KNOWN_INTERFACE_EQUITY_TOKEN = 0xab9885bb;

    // Payment tokens (collection) keccak256("PaymentToken")
    bytes4 internal constant KNOWN_INTERFACE_PAYMENT_TOKEN = 0xb2a0042a;

    // ETO Contraints, aka Products keccak256("ETOTermsConstraints")
    bytes4 internal constant KNOWN_INTERFACE_ETO_TERMS_CONSTRAINTS = 0xce2be4f5;
}

contract NeumarkIssuanceCurve {

    ////////////////////////
    // Constants
    ////////////////////////

    // maximum number of neumarks that may be created
    uint256 private constant NEUMARK_CAP = 1500000000000000000000000000;

    // initial neumark reward fraction (controls curve steepness)
    uint256 private constant INITIAL_REWARD_FRACTION = 6500000000000000000;

    // stop issuing new Neumarks above this Euro value (as it goes quickly to zero)
    uint256 private constant ISSUANCE_LIMIT_EUR_ULPS = 8300000000000000000000000000;

    // approximate curve linearly above this Euro value
    uint256 private constant LINEAR_APPROX_LIMIT_EUR_ULPS = 2100000000000000000000000000;
    uint256 private constant NEUMARKS_AT_LINEAR_LIMIT_ULPS = 1499832501287264827896539871;

    uint256 private constant TOT_LINEAR_NEUMARKS_ULPS = NEUMARK_CAP - NEUMARKS_AT_LINEAR_LIMIT_ULPS;
    uint256 private constant TOT_LINEAR_EUR_ULPS = ISSUANCE_LIMIT_EUR_ULPS - LINEAR_APPROX_LIMIT_EUR_ULPS;

    ////////////////////////
    // Public functions
    ////////////////////////

    /// @notice returns additional amount of neumarks issued for euroUlps at totalEuroUlps
    /// @param totalEuroUlps actual curve position from which neumarks will be issued
    /// @param euroUlps amount against which neumarks will be issued
    function incremental(uint256 totalEuroUlps, uint256 euroUlps)
        public
        pure
        returns (uint256 neumarkUlps)
    {
        require(totalEuroUlps + euroUlps >= totalEuroUlps);
        uint256 from = cumulative(totalEuroUlps);
        uint256 to = cumulative(totalEuroUlps + euroUlps);
        // as expansion is not monotonic for large totalEuroUlps, assert below may fail
        // example: totalEuroUlps=1.999999999999999999999000000e+27 and euroUlps=50
        assert(to >= from);
        return to - from;
    }

    /// @notice returns amount of euro corresponding to burned neumarks
    /// @param totalEuroUlps actual curve position from which neumarks will be burned
    /// @param burnNeumarkUlps amount of neumarks to burn
    function incrementalInverse(uint256 totalEuroUlps, uint256 burnNeumarkUlps)
        public
        pure
        returns (uint256 euroUlps)
    {
        uint256 totalNeumarkUlps = cumulative(totalEuroUlps);
        require(totalNeumarkUlps >= burnNeumarkUlps);
        uint256 fromNmk = totalNeumarkUlps - burnNeumarkUlps;
        uint newTotalEuroUlps = cumulativeInverse(fromNmk, 0, totalEuroUlps);
        // yes, this may overflow due to non monotonic inverse function
        assert(totalEuroUlps >= newTotalEuroUlps);
        return totalEuroUlps - newTotalEuroUlps;
    }

    /// @notice returns amount of euro corresponding to burned neumarks
    /// @param totalEuroUlps actual curve position from which neumarks will be burned
    /// @param burnNeumarkUlps amount of neumarks to burn
    /// @param minEurUlps euro amount to start inverse search from, inclusive
    /// @param maxEurUlps euro amount to end inverse search to, inclusive
    function incrementalInverse(uint256 totalEuroUlps, uint256 burnNeumarkUlps, uint256 minEurUlps, uint256 maxEurUlps)
        public
        pure
        returns (uint256 euroUlps)
    {
        uint256 totalNeumarkUlps = cumulative(totalEuroUlps);
        require(totalNeumarkUlps >= burnNeumarkUlps);
        uint256 fromNmk = totalNeumarkUlps - burnNeumarkUlps;
        uint newTotalEuroUlps = cumulativeInverse(fromNmk, minEurUlps, maxEurUlps);
        // yes, this may overflow due to non monotonic inverse function
        assert(totalEuroUlps >= newTotalEuroUlps);
        return totalEuroUlps - newTotalEuroUlps;
    }

    /// @notice finds total amount of neumarks issued for given amount of Euro
    /// @dev binomial expansion does not guarantee monotonicity on uint256 precision for large euroUlps
    ///     function below is not monotonic
    function cumulative(uint256 euroUlps)
        public
        pure
        returns(uint256 neumarkUlps)
    {
        // Return the cap if euroUlps is above the limit.
        if (euroUlps >= ISSUANCE_LIMIT_EUR_ULPS) {
            return NEUMARK_CAP;
        }
        // use linear approximation above limit below
        // binomial expansion does not guarantee monotonicity on uint256 precision for large euroUlps
        if (euroUlps >= LINEAR_APPROX_LIMIT_EUR_ULPS) {
            // (euroUlps - LINEAR_APPROX_LIMIT_EUR_ULPS) is small so expression does not overflow
            return NEUMARKS_AT_LINEAR_LIMIT_ULPS + (TOT_LINEAR_NEUMARKS_ULPS * (euroUlps - LINEAR_APPROX_LIMIT_EUR_ULPS)) / TOT_LINEAR_EUR_ULPS;
        }

        // Approximate cap-cap·(1-1/D)^n using the Binomial expansion
        // http://galileo.phys.virginia.edu/classes/152.mf1i.spring02/Exponential_Function.htm
        // Function[imax, -CAP*Sum[(-IR*EUR/CAP)^i/Factorial[i], {i, imax}]]
        // which may be simplified to
        // Function[imax, -CAP*Sum[(EUR)^i/(Factorial[i]*(-d)^i), {i, 1, imax}]]
        // where d = cap/initial_reward
        uint256 d = 230769230769230769230769231; // NEUMARK_CAP / INITIAL_REWARD_FRACTION
        uint256 term = NEUMARK_CAP;
        uint256 sum = 0;
        uint256 denom = d;
        do assembly {
            // We use assembler primarily to avoid the expensive
            // divide-by-zero check solc inserts for the / operator.
            term  := div(mul(term, euroUlps), denom)
            sum   := add(sum, term)
            denom := add(denom, d)
            // sub next term as we have power of negative value in the binomial expansion
            term  := div(mul(term, euroUlps), denom)
            sum   := sub(sum, term)
            denom := add(denom, d)
        } while (term != 0);
        return sum;
    }

    /// @notice find issuance curve inverse by binary search
    /// @param neumarkUlps neumark amount to compute inverse for
    /// @param minEurUlps minimum search range for the inverse, inclusive
    /// @param maxEurUlps maxium search range for the inverse, inclusive
    /// @dev in case of approximate search (no exact inverse) upper element of minimal search range is returned
    /// @dev in case of many possible inverses, the lowest one will be used (if range permits)
    /// @dev corresponds to a linear search that returns first euroUlp value that has cumulative() equal or greater than neumarkUlps
    function cumulativeInverse(uint256 neumarkUlps, uint256 minEurUlps, uint256 maxEurUlps)
        public
        pure
        returns (uint256 euroUlps)
    {
        require(maxEurUlps >= minEurUlps);
        require(cumulative(minEurUlps) <= neumarkUlps);
        require(cumulative(maxEurUlps) >= neumarkUlps);
        uint256 min = minEurUlps;
        uint256 max = maxEurUlps;

        // Binary search
        while (max > min) {
            uint256 mid = (max + min) / 2;
            uint256 val = cumulative(mid);
            // exact solution should not be used, a late points of the curve when many euroUlps are needed to
            // increase by one nmkUlp this will lead to  "indeterministic" inverse values that depend on the initial min and max
            // and further binary division -> you can land at any of the euro value that is mapped to the same nmk value
            // with condition below removed, binary search will point to the lowest eur value possible which is good because it cannot be exploited even with 0 gas costs
            /* if (val == neumarkUlps) {
                return mid;
            }*/
            // NOTE: approximate search (no inverse) must return upper element of the final range
            //  last step of approximate search is always (min, min+1) so new mid is (2*min+1)/2 => min
            //  so new min = mid + 1 = max which was upper range. and that ends the search
            // NOTE: when there are multiple inverses for the same neumarkUlps, the `max` will be dragged down
            //  by `max = mid` expression to the lowest eur value of inverse. works only for ranges that cover all points of multiple inverse
            if (val < neumarkUlps) {
                min = mid + 1;
            } else {
                max = mid;
            }
        }
        // NOTE: It is possible that there is no inverse
        //  for example curve(0) = 0 and curve(1) = 6, so
        //  there is no value y such that curve(y) = 5.
        //  When there is no inverse, we must return upper element of last search range.
        //  This has the effect of reversing the curve less when
        //  burning Neumarks. This ensures that Neumarks can always
        //  be burned. It also ensure that the total supply of Neumarks
        //  remains below the cap.
        return max;
    }

    function neumarkCap()
        public
        pure
        returns (uint256)
    {
        return NEUMARK_CAP;
    }

    function initialRewardFraction()
        public
        pure
        returns (uint256)
    {
        return INITIAL_REWARD_FRACTION;
    }
}

/// @title advances snapshot id on demand
/// @dev see Snapshot folder for implementation examples ie. DailyAndSnapshotable contract
contract ISnapshotable {

    ////////////////////////
    // Events
    ////////////////////////

    /// @dev should log each new snapshot id created, including snapshots created automatically via MSnapshotPolicy
    event LogSnapshotCreated(uint256 snapshotId);

    ////////////////////////
    // Public functions
    ////////////////////////

    /// always creates new snapshot id which gets returned
    /// however, there is no guarantee that any snapshot will be created with this id, this depends on the implementation of MSnaphotPolicy
    function createSnapshot()
        public
        returns (uint256);

    /// upper bound of series snapshotIds for which there's a value
    function currentSnapshotId()
        public
        constant
        returns (uint256);
}

/// @title creates snapshot id on each day boundary and allows to create additional snapshots within a given day
/// @dev snapshots are encoded in single uint256, where high 128 bits represents a day number (from unix epoch) and low 128 bits represents additional snapshots within given day create via ISnapshotable
contract DailyAndSnapshotable is
    Daily,
    ISnapshotable
{

    ////////////////////////
    // Mutable state
    ////////////////////////

    uint256 private _currentSnapshotId;

    ////////////////////////
    // Constructor
    ////////////////////////

    /// @param start snapshotId from which to start generating values
    /// @dev start must be for the same day or 0, required for token cloning
    constructor(uint256 start)
        internal
        Daily(start)
    {
        if (start > 0) {
            _currentSnapshotId = start;
        }
    }

    ////////////////////////
    // Public functions
    ////////////////////////

    //
    // Implements ISnapshotable
    //

    function createSnapshot()
        public
        returns (uint256)
    {
        uint256 base = dayBase(uint128(block.timestamp));

        if (base > _currentSnapshotId) {
            // New day has started, create snapshot for midnight
            _currentSnapshotId = base;
        } else {
            // within single day, increase counter (assume 2**128 will not be crossed)
            _currentSnapshotId += 1;
        }

        // Log and return
        emit LogSnapshotCreated(_currentSnapshotId);
        return _currentSnapshotId;
    }

    ////////////////////////
    // Internal functions
    ////////////////////////

    //
    // Implements MSnapshotPolicy
    //

    function mAdvanceSnapshotId()
        internal
        returns (uint256)
    {
        uint256 base = dayBase(uint128(block.timestamp));

        // New day has started
        if (base > _currentSnapshotId) {
            _currentSnapshotId = base;
            emit LogSnapshotCreated(base);
        }

        return _currentSnapshotId;
    }

    function mCurrentSnapshotId()
        internal
        constant
        returns (uint256)
    {
        uint256 base = dayBase(uint128(block.timestamp));

        return base > _currentSnapshotId ? base : _currentSnapshotId;
    }
}

/// @title old ERC223 callback function
/// @dev as used in Neumark and ICBMEtherToken
contract IERC223LegacyCallback {

    ////////////////////////
    // Public functions
    ////////////////////////

    function onTokenTransfer(address from, uint256 amount, bytes data)
        public;

}

contract Neumark is
    AccessControlled,
    AccessRoles,
    Agreement,
    DailyAndSnapshotable,
    StandardSnapshotToken,
    TokenMetadata,
    IERC223Token,
    NeumarkIssuanceCurve,
    Reclaimable,
    IsContract
{

    ////////////////////////
    // Constants
    ////////////////////////

    string private constant TOKEN_NAME = "Neumark";

    uint8  private constant TOKEN_DECIMALS = 18;

    string private constant TOKEN_SYMBOL = "NEU";

    string private constant VERSION = "NMK_1.0";

    ////////////////////////
    // Mutable state
    ////////////////////////

    // disable transfers when Neumark is created
    bool private _transferEnabled = false;

    // at which point on curve new Neumarks will be created, see NeumarkIssuanceCurve contract
    // do not use to get total invested funds. see burn(). this is just a cache for expensive inverse function
    uint256 private _totalEurUlps;

    ////////////////////////
    // Events
    ////////////////////////

    event LogNeumarksIssued(
        address indexed owner,
        uint256 euroUlps,
        uint256 neumarkUlps
    );

    event LogNeumarksBurned(
        address indexed owner,
        uint256 euroUlps,
        uint256 neumarkUlps
    );

    ////////////////////////
    // Constructor
    ////////////////////////

    constructor(
        IAccessPolicy accessPolicy,
        IEthereumForkArbiter forkArbiter
    )
        AccessRoles()
        Agreement(accessPolicy, forkArbiter)
        StandardSnapshotToken(
            IClonedTokenParent(0x0),
            0
        )
        TokenMetadata(
            TOKEN_NAME,
            TOKEN_DECIMALS,
            TOKEN_SYMBOL,
            VERSION
        )
        DailyAndSnapshotable(0)
        NeumarkIssuanceCurve()
        Reclaimable()
        public
    {}

    ////////////////////////
    // Public functions
    ////////////////////////

    /// @notice issues new Neumarks to msg.sender with reward at current curve position
    ///     moves curve position by euroUlps
    ///     callable only by ROLE_NEUMARK_ISSUER
    function issueForEuro(uint256 euroUlps)
        public
        only(ROLE_NEUMARK_ISSUER)
        acceptAgreement(msg.sender)
        returns (uint256)
    {
        require(_totalEurUlps + euroUlps >= _totalEurUlps);
        uint256 neumarkUlps = incremental(_totalEurUlps, euroUlps);
        _totalEurUlps += euroUlps;
        mGenerateTokens(msg.sender, neumarkUlps);
        emit LogNeumarksIssued(msg.sender, euroUlps, neumarkUlps);
        return neumarkUlps;
    }

    /// @notice used by ROLE_NEUMARK_ISSUER to transer newly issued neumarks
    ///     typically to the investor and platform operator
    function distribute(address to, uint256 neumarkUlps)
        public
        only(ROLE_NEUMARK_ISSUER)
        acceptAgreement(to)
    {
        mTransfer(msg.sender, to, neumarkUlps);
    }

    /// @notice msg.sender can burn their Neumarks, curve is rolled back using inverse
    ///     curve. as a result cost of Neumark gets lower (reward is higher)
    function burn(uint256 neumarkUlps)
        public
        only(ROLE_NEUMARK_BURNER)
    {
        burnPrivate(neumarkUlps, 0, _totalEurUlps);
    }

    /// @notice executes as function above but allows to provide search range for low gas burning
    function burn(uint256 neumarkUlps, uint256 minEurUlps, uint256 maxEurUlps)
        public
        only(ROLE_NEUMARK_BURNER)
    {
        burnPrivate(neumarkUlps, minEurUlps, maxEurUlps);
    }

    function enableTransfer(bool enabled)
        public
        only(ROLE_TRANSFER_ADMIN)
    {
        _transferEnabled = enabled;
    }

    function createSnapshot()
        public
        only(ROLE_SNAPSHOT_CREATOR)
        returns (uint256)
    {
        return DailyAndSnapshotable.createSnapshot();
    }

    function transferEnabled()
        public
        constant
        returns (bool)
    {
        return _transferEnabled;
    }

    function totalEuroUlps()
        public
        constant
        returns (uint256)
    {
        return _totalEurUlps;
    }

    function incremental(uint256 euroUlps)
        public
        constant
        returns (uint256 neumarkUlps)
    {
        return incremental(_totalEurUlps, euroUlps);
    }

    //
    // Implements IERC223Token with IERC223Callback (onTokenTransfer) callback
    //

    // old implementation of ERC223 that was actual when ICBM was deployed
    // as Neumark is already deployed this function keeps old behavior for testing
    function transfer(address to, uint256 amount, bytes data)
        public
        returns (bool)
    {
        // it is necessary to point out implementation to be called
        BasicSnapshotToken.mTransfer(msg.sender, to, amount);

        // Notify the receiving contract.
        if (isContract(to)) {
            IERC223LegacyCallback(to).onTokenTransfer(msg.sender, amount, data);
        }
        return true;
    }

    ////////////////////////
    // Internal functions
    ////////////////////////

    //
    // Implements MTokenController
    //

    function mOnTransfer(
        address from,
        address, // to
        uint256 // amount
    )
        internal
        acceptAgreement(from)
        returns (bool allow)
    {
        // must have transfer enabled or msg.sender is Neumark issuer
        return _transferEnabled || accessPolicy().allowed(msg.sender, ROLE_NEUMARK_ISSUER, this, msg.sig);
    }

    function mOnApprove(
        address owner,
        address, // spender,
        uint256 // amount
    )
        internal
        acceptAgreement(owner)
        returns (bool allow)
    {
        return true;
    }

    ////////////////////////
    // Private functions
    ////////////////////////

    function burnPrivate(uint256 burnNeumarkUlps, uint256 minEurUlps, uint256 maxEurUlps)
        private
    {
        uint256 prevEuroUlps = _totalEurUlps;
        // burn first in the token to make sure balance/totalSupply is not crossed
        mDestroyTokens(msg.sender, burnNeumarkUlps);
        _totalEurUlps = cumulativeInverse(totalSupply(), minEurUlps, maxEurUlps);
        // actually may overflow on non-monotonic inverse
        assert(prevEuroUlps >= _totalEurUlps);
        uint256 euroUlps = prevEuroUlps - _totalEurUlps;
        emit LogNeumarksBurned(msg.sender, euroUlps, burnNeumarkUlps);
    }
}

/// @title makes modern ERC223 contracts compatible with the legacy implementation
/// @dev should be used for all receivers of tokens sent by ICBMEtherToken and NEU
contract ERC223LegacyCallbackCompat {

    ////////////////////////
    // Public functions
    ////////////////////////

    function onTokenTransfer(address wallet, uint256 amount, bytes data)
        public
    {
        tokenFallback(wallet, amount, data);
    }

    function tokenFallback(address wallet, uint256 amount, bytes data)
        public;

}

/// @title granular fee disbursal controller
contract IFeeDisbursalController is
    IContractId
{


    ////////////////////////
    // Public functions
    ////////////////////////

    /// @notice check whether claimer can accept disbursal offer
    function onAccept(address /*token*/, address /*proRataToken*/, address claimer)
        public
        constant
        returns (bool allow);

    /// @notice check whether claimer can reject disbursal offer
    function onReject(address /*token*/, address /*proRataToken*/, address claimer)
        public
        constant
        returns (bool allow);

    /// @notice check wether this disbursal can happen
    function onDisburse(address token, address disburser, uint256 amount, address proRataToken, uint256 recycleAfterPeriod)
        public
        constant
        returns (bool allow);

    /// @notice check wether this recycling can happen
    function onRecycle(address token, address /*proRataToken*/, address[] investors, uint256 until)
        public
        constant
        returns (bool allow);

    /// @notice check wether the disbursal controller may be changed
    function onChangeFeeDisbursalController(address sender, IFeeDisbursalController newController)
        public
        constant
        returns (bool);

}

/// @title disburse payment token amount to snapshot token holders
/// @dev payment token received via ERC223 Transfer
contract IFeeDisbursal is
    IERC223Callback,
    IERC677Callback,
    IERC223LegacyCallback,
    ERC223LegacyCallbackCompat,
    IContractId
    {

    ////////////////////////
    // Events
    ////////////////////////

    event LogDisbursalCreated(
        address indexed proRataToken,
        address indexed token,
        uint256 amount,
        uint256 recycleAfterDuration,
        address disburser,
        uint256 index
    );

    event LogDisbursalAccepted(
        address indexed claimer,
        address token,
        address proRataToken,
        uint256 amount,
        uint256 nextIndex
    );

    event LogDisbursalRejected(
        address indexed claimer,
        address token,
        address proRataToken,
        uint256 amount,
        uint256 nextIndex
    );

    event LogFundsRecycled(
        address indexed proRataToken,
        address indexed token,
        uint256 amount,
        address by
    );

    event LogChangeFeeDisbursalController(
        address oldController,
        address newController,
        address by
    );

    ////////////////////////
    // Types
    ////////////////////////
    struct Disbursal {
        // snapshop ID of the pro-rata token, which will define which amounts to disburse against
        uint256 snapshotId;
        // amount of tokens to disburse
        uint256 amount;
        // timestamp after which claims to this token can be recycled
        uint128 recycleableAfterTimestamp;
        // timestamp on which token were disbursed
        uint128 disbursalTimestamp;
        // contract sending the disbursal
        address disburser;
    }

    ////////////////////////
    // Constants
    ////////////////////////
    uint256 internal constant UINT256_MAX = 2**256 - 1;


    ////////////////////////
    // Public functions
    ////////////////////////

    /// @notice get the disbursal at a given index for a given token
    /// @param token address of the disbursable token
    /// @param proRataToken address of the token used to determine the user pro rata amount, must be a snapshottoken
    /// @param index until what index to claim to
    function getDisbursal(address token, address proRataToken, uint256 index)
        public
        constant
    returns (
        uint256 snapshotId,
        uint256 amount,
        uint256 recycleableAfterTimestamp,
        uint256 disburseTimestamp,
        address disburser
        );

    /// @notice get disbursals for current snapshot id of the proRataToken that cannot be claimed yet
    /// @param token address of the disbursable token
    /// @param proRataToken address of the token used to determine the user pro rata amount, must be a snapshottoken
    /// @return array of (snapshotId, amount, index) ordered by index. full disbursal information can be retrieved via index
    function getNonClaimableDisbursals(address token, address proRataToken)
        public
        constant
        returns (uint256[3][] memory disbursals);

    /// @notice get count of disbursals for given token
    /// @param token address of the disbursable token
    /// @param proRataToken address of the token used to determine the user pro rata amount, must be a snapshottoken
    function getDisbursalCount(address token, address proRataToken)
        public
        constant
        returns (uint256);

    /// @notice accepts the token disbursal offer and claim offered tokens, to be called by an investor
    /// @param token address of the disbursable token
    /// @param proRataToken address of the token used to determine the user pro rata amount, must be a snapshottoken
    /// @param until until what index to claim to, noninclusive, use 2**256 to accept all disbursals
    function accept(address token, ITokenSnapshots proRataToken, uint256 until)
        public;

    /// @notice accepts disbursals of multiple tokens and receives them, to be called an investor
    /// @param tokens addresses of the disbursable token
    /// @param proRataToken address of the token used to determine the user pro rata amount, must be a snapshottoken
    function acceptMultipleByToken(address[] tokens, ITokenSnapshots proRataToken)
        public;

    /// @notice accepts disbursals for single token against many pro rata tokens
    /// @param token address of the disbursable token
    /// @param proRataTokens addresses of the tokens used to determine the user pro rata amount, must be a snapshottoken
    /// @dev this should let save a lot on gas by eliminating multiple transfers and some checks
    function acceptMultipleByProRataToken(address token, ITokenSnapshots[] proRataTokens)
        public;

    /// @notice rejects disbursal of token which leads to recycle and disbursal of rejected amount
    /// @param token address of the disbursable token
    /// @param proRataToken address of the token used to determine the user pro rata amount, must be a snapshottoken
    /// @param until until what index to claim to, noninclusive, use 2**256 to reject all disbursals
    function reject(address token, ITokenSnapshots proRataToken, uint256 until)
        public;

    /// @notice check how many tokens of a certain kind can be claimed by an account
    /// @param token address of the disbursable token
    /// @param proRataToken address of the token used to determine the user pro rata amount, must be a snapshottoken
    /// @param claimer address of the claimer that would receive the funds
    /// @param until until what index to claim to, noninclusive, use 2**256 to reject all disbursals
    /// @return (amount that can be claimed, total disbursed amount, time to recycle of first disbursal, first disbursal index)
    function claimable(address token, ITokenSnapshots proRataToken, address claimer, uint256 until)
        public
        constant
        returns (uint256 claimableAmount, uint256 totalAmount, uint256 recycleableAfterTimestamp, uint256 firstIndex);

    /// @notice check how much fund for each disbursable tokens can be claimed by claimer
    /// @param tokens addresses of the disbursable token
    /// @param proRataToken address of the token used to determine the user pro rata amount, must be a snapshottoken
    /// @param claimer address of the claimer that would receive the funds
    /// @return array of (amount that can be claimed, total disbursed amount, time to recycle of first disbursal, first disbursal index)
    /// @dev claimbles are returned in the same order as tokens were specified
    function claimableMutipleByToken(address[] tokens, ITokenSnapshots proRataToken, address claimer)
        public
        constant
        returns (uint256[4][] claimables);

    /// @notice check how many tokens can be claimed against many pro rata tokens
    /// @param token address of the disbursable token
    /// @param proRataTokens addresses of the tokens used to determine the user pro rata amount, must be a snapshottoken
    /// @param claimer address of the claimer that would receive the funds
    /// @return array of (amount that can be claimed, total disbursed amount, time to recycle of first disbursal, first disbursal index)
    function claimableMutipleByProRataToken(address token, ITokenSnapshots[] proRataTokens, address claimer)
        public
        constant
        returns (uint256[4][] claimables);


    /// @notice recycle a token for multiple investors
    /// @param token address of the recyclable token
    /// @param proRataToken address of the token used to determine the user pro rata amount, must be a snapshottoken
    /// @param investors list of investors we want to recycle tokens for
    /// @param until until what index to recycle to
    function recycle(address token, ITokenSnapshots proRataToken, address[] investors, uint256 until)
        public;

    /// @notice check how much we can recycle for multiple investors
    /// @param token address of the recyclable token
    /// @param proRataToken address of the token used to determine the user pro rata amount, must be a snapshottoken
    /// @param investors list of investors we want to recycle tokens for
    /// @param until until what index to recycle to
    function recycleable(address token, ITokenSnapshots proRataToken, address[] investors, uint256 until)
        public
        constant
        returns (uint256);

    /// @notice get current controller
    function feeDisbursalController()
        public
        constant
        returns (IFeeDisbursalController);

    /// @notice update current controller
    function changeFeeDisbursalController(IFeeDisbursalController newController)
        public;
}

/// @title disburse payment token amount to snapshot token holders
/// @dev payment token received via ERC223 Transfer
contract IPlatformPortfolio is IERC223Callback {
    // TODO: declare interface
}

contract ITokenExchangeRateOracle {
    /// @notice provides actual price of 'numeratorToken' in 'denominatorToken'
    ///     returns timestamp at which price was obtained in oracle
    function getExchangeRate(address numeratorToken, address denominatorToken)
        public
        constant
        returns (uint256 rateFraction, uint256 timestamp);

    /// @notice allows to retreive multiple exchange rates in once call
    function getExchangeRates(address[] numeratorTokens, address[] denominatorTokens)
        public
        constant
        returns (uint256[] rateFractions, uint256[] timestamps);
}

/// @title root of trust and singletons + known interface registry
/// provides a root which holds all interfaces platform trust, this includes
/// singletons - for which accessors are provided
/// collections of known instances of interfaces
/// @dev interfaces are identified by bytes4, see KnownInterfaces.sol
contract Universe is
    Agreement,
    IContractId,
    KnownInterfaces
{
    ////////////////////////
    // Events
    ////////////////////////

    /// raised on any change of singleton instance
    /// @dev for convenience we provide previous instance of singleton in replacedInstance
    event LogSetSingleton(
        bytes4 interfaceId,
        address instance,
        address replacedInstance
    );

    /// raised on add/remove interface instance in collection
    event LogSetCollectionInterface(
        bytes4 interfaceId,
        address instance,
        bool isSet
    );

    ////////////////////////
    // Mutable state
    ////////////////////////

    // mapping of known contracts to addresses of singletons
    mapping(bytes4 => address) private _singletons;

    // mapping of known interfaces to collections of contracts
    mapping(bytes4 =>
        mapping(address => bool)) private _collections; // solium-disable-line indentation

    // known instances
    mapping(address => bytes4[]) private _instances;


    ////////////////////////
    // Constructor
    ////////////////////////

    constructor(
        IAccessPolicy accessPolicy,
        IEthereumForkArbiter forkArbiter
    )
        Agreement(accessPolicy, forkArbiter)
        public
    {
        setSingletonPrivate(KNOWN_INTERFACE_ACCESS_POLICY, accessPolicy);
        setSingletonPrivate(KNOWN_INTERFACE_FORK_ARBITER, forkArbiter);
    }

    ////////////////////////
    // Public methods
    ////////////////////////

    /// get singleton instance for 'interfaceId'
    function getSingleton(bytes4 interfaceId)
        public
        constant
        returns (address)
    {
        return _singletons[interfaceId];
    }

    function getManySingletons(bytes4[] interfaceIds)
        public
        constant
        returns (address[])
    {
        address[] memory addresses = new address[](interfaceIds.length);
        uint256 idx;
        while(idx < interfaceIds.length) {
            addresses[idx] = _singletons[interfaceIds[idx]];
            idx += 1;
        }
        return addresses;
    }

    /// checks of 'instance' is instance of interface 'interfaceId'
    function isSingleton(bytes4 interfaceId, address instance)
        public
        constant
        returns (bool)
    {
        return _singletons[interfaceId] == instance;
    }

    /// checks if 'instance' is one of instances of 'interfaceId'
    function isInterfaceCollectionInstance(bytes4 interfaceId, address instance)
        public
        constant
        returns (bool)
    {
        return _collections[interfaceId][instance];
    }

    function isAnyOfInterfaceCollectionInstance(bytes4[] interfaceIds, address instance)
        public
        constant
        returns (bool)
    {
        uint256 idx;
        while(idx < interfaceIds.length) {
            if (_collections[interfaceIds[idx]][instance]) {
                return true;
            }
            idx += 1;
        }
        return false;
    }

    /// gets all interfaces of given instance
    function getInterfacesOfInstance(address instance)
        public
        constant
        returns (bytes4[] interfaces)
    {
        return _instances[instance];
    }

    /// sets 'instance' of singleton with interface 'interfaceId'
    function setSingleton(bytes4 interfaceId, address instance)
        public
        only(ROLE_UNIVERSE_MANAGER)
    {
        setSingletonPrivate(interfaceId, instance);
    }

    /// convenience method for setting many singleton instances
    function setManySingletons(bytes4[] interfaceIds, address[] instances)
        public
        only(ROLE_UNIVERSE_MANAGER)
    {
        require(interfaceIds.length == instances.length);
        uint256 idx;
        while(idx < interfaceIds.length) {
            setSingletonPrivate(interfaceIds[idx], instances[idx]);
            idx += 1;
        }
    }

    /// set or unset 'instance' with 'interfaceId' in collection of instances
    function setCollectionInterface(bytes4 interfaceId, address instance, bool set)
        public
        only(ROLE_UNIVERSE_MANAGER)
    {
        setCollectionPrivate(interfaceId, instance, set);
    }

    /// set or unset 'instance' in many collections of instances
    function setInterfaceInManyCollections(bytes4[] interfaceIds, address instance, bool set)
        public
        only(ROLE_UNIVERSE_MANAGER)
    {
        uint256 idx;
        while(idx < interfaceIds.length) {
            setCollectionPrivate(interfaceIds[idx], instance, set);
            idx += 1;
        }
    }

    /// set or unset array of collection
    function setCollectionsInterfaces(bytes4[] interfaceIds, address[] instances, bool[] set_flags)
        public
        only(ROLE_UNIVERSE_MANAGER)
    {
        require(interfaceIds.length == instances.length);
        require(interfaceIds.length == set_flags.length);
        uint256 idx;
        while(idx < interfaceIds.length) {
            setCollectionPrivate(interfaceIds[idx], instances[idx], set_flags[idx]);
            idx += 1;
        }
    }

    //
    // Implements IContractId
    //

    function contractId() public pure returns (bytes32 id, uint256 version) {
        return (0x8b57bfe21a3ef4854e19d702063b6cea03fa514162f8ff43fde551f06372fefd, 0);
    }

    ////////////////////////
    // Getters
    ////////////////////////

    function accessPolicy() public constant returns (IAccessPolicy) {
        return IAccessPolicy(_singletons[KNOWN_INTERFACE_ACCESS_POLICY]);
    }

    function forkArbiter() public constant returns (IEthereumForkArbiter) {
        return IEthereumForkArbiter(_singletons[KNOWN_INTERFACE_FORK_ARBITER]);
    }

    function neumark() public constant returns (Neumark) {
        return Neumark(_singletons[KNOWN_INTERFACE_NEUMARK]);
    }

    function etherToken() public constant returns (IERC223Token) {
        return IERC223Token(_singletons[KNOWN_INTERFACE_ETHER_TOKEN]);
    }

    function euroToken() public constant returns (IERC223Token) {
        return IERC223Token(_singletons[KNOWN_INTERFACE_EURO_TOKEN]);
    }

    function etherLock() public constant returns (address) {
        return _singletons[KNOWN_INTERFACE_ETHER_LOCK];
    }

    function euroLock() public constant returns (address) {
        return _singletons[KNOWN_INTERFACE_EURO_LOCK];
    }

    function icbmEtherLock() public constant returns (address) {
        return _singletons[KNOWN_INTERFACE_ICBM_ETHER_LOCK];
    }

    function icbmEuroLock() public constant returns (address) {
        return _singletons[KNOWN_INTERFACE_ICBM_EURO_LOCK];
    }

    function identityRegistry() public constant returns (address) {
        return IIdentityRegistry(_singletons[KNOWN_INTERFACE_IDENTITY_REGISTRY]);
    }

    function tokenExchangeRateOracle() public constant returns (address) {
        return ITokenExchangeRateOracle(_singletons[KNOWN_INTERFACE_TOKEN_EXCHANGE_RATE_ORACLE]);
    }

    function feeDisbursal() public constant returns (address) {
        return IFeeDisbursal(_singletons[KNOWN_INTERFACE_FEE_DISBURSAL]);
    }

    function platformPortfolio() public constant returns (address) {
        return IPlatformPortfolio(_singletons[KNOWN_INTERFACE_PLATFORM_PORTFOLIO]);
    }

    function tokenExchange() public constant returns (address) {
        return _singletons[KNOWN_INTERFACE_TOKEN_EXCHANGE];
    }

    function gasExchange() public constant returns (address) {
        return _singletons[KNOWN_INTERFACE_GAS_EXCHANGE];
    }

    function platformTerms() public constant returns (address) {
        return _singletons[KNOWN_INTERFACE_PLATFORM_TERMS];
    }

    ////////////////////////
    // Private methods
    ////////////////////////

    function setSingletonPrivate(bytes4 interfaceId, address instance)
        private
    {
        require(interfaceId != KNOWN_INTERFACE_UNIVERSE, "NF_UNI_NO_UNIVERSE_SINGLETON");
        address replacedInstance = _singletons[interfaceId];
        // do nothing if not changing
        if (replacedInstance != instance) {
            dropInstance(replacedInstance, interfaceId);
            addInstance(instance, interfaceId);
            _singletons[interfaceId] = instance;
        }

        emit LogSetSingleton(interfaceId, instance, replacedInstance);
    }

    function setCollectionPrivate(bytes4 interfaceId, address instance, bool set)
        private
    {
        // do nothing if not changing
        if (_collections[interfaceId][instance] == set) {
            return;
        }
        _collections[interfaceId][instance] = set;
        if (set) {
            addInstance(instance, interfaceId);
        } else {
            dropInstance(instance, interfaceId);
        }
        emit LogSetCollectionInterface(interfaceId, instance, set);
    }

    function addInstance(address instance, bytes4 interfaceId)
        private
    {
        if (instance == address(0)) {
            // do not add null instance
            return;
        }
        bytes4[] storage current = _instances[instance];
        uint256 idx;
        while(idx < current.length) {
            // instancy has this interface already, do nothing
            if (current[idx] == interfaceId)
                return;
            idx += 1;
        }
        // new interface
        current.push(interfaceId);
    }

    function dropInstance(address instance, bytes4 interfaceId)
        private
    {
        if (instance == address(0)) {
            // do not drop null instance
            return;
        }
        bytes4[] storage current = _instances[instance];
        uint256 idx;
        uint256 last = current.length - 1;
        while(idx <= last) {
            if (current[idx] == interfaceId) {
                // delete element
                if (idx < last) {
                    // if not last element move last element to idx being deleted
                    current[idx] = current[last];
                }
                // delete last element
                current.length -= 1;
                return;
            }
            idx += 1;
        }
    }
}

/// @title hooks token controller to token contract and allows to replace it
contract ITokenControllerHook {

    ////////////////////////
    // Events
    ////////////////////////

    event LogChangeTokenController(
        address oldController,
        address newController,
        address by
    );

    ////////////////////////
    // Public functions
    ////////////////////////

    /// @notice replace current token controller
    /// @dev please note that this process is also controlled by existing controller
    function changeTokenController(address newController)
        public;

    /// @notice returns current controller
    function tokenController()
        public
        constant
        returns (address currentController);

}

/// @title state space of ETOCommitment
contract IETOCommitmentStates {
    ////////////////////////
    // Types
    ////////////////////////

    // order must reflect time precedence, do not change order below
    enum ETOState {
        Setup, // Initial state
        Whitelist,
        Public,
        Signing,
        Claim,
        Payout, // Terminal state
        Refund // Terminal state
    }

    // number of states in enum
    uint256 constant internal ETO_STATES_COUNT = 7;
}

/// @title provides callback on state transitions
/// @dev observer called after the state() of commitment contract was set
contract IETOCommitmentObserver is IETOCommitmentStates {
    function commitmentObserver() public constant returns (address);
    function onStateTransition(ETOState oldState, ETOState newState) public;
}

/// @title granular token controller based on MSnapshotToken observer pattern
contract ITokenController {

    ////////////////////////
    // Public functions
    ////////////////////////

    /// @notice see MTokenTransferController
    /// @dev additionally passes broker that is executing transaction between from and to
    ///      for unbrokered transfer, broker == from
    function onTransfer(address broker, address from, address to, uint256 amount)
        public
        constant
        returns (bool allow);

    /// @notice see MTokenAllowanceController
    function onApprove(address owner, address spender, uint256 amount)
        public
        constant
        returns (bool allow);

    /// @notice see MTokenMint
    function onGenerateTokens(address sender, address owner, uint256 amount)
        public
        constant
        returns (bool allow);

    /// @notice see MTokenMint
    function onDestroyTokens(address sender, address owner, uint256 amount)
        public
        constant
        returns (bool allow);

    /// @notice controls if sender can change controller to newController
    /// @dev for this to succeed TYPICALLY current controller must be already migrated to a new one
    function onChangeTokenController(address sender, address newController)
        public
        constant
        returns (bool);

    /// @notice overrides spender allowance
    /// @dev may be used to implemented forced transfers in which token controller may override approved allowance
    ///      with any > 0 value and then use transferFrom to execute such transfer
    ///      This by definition creates non-trustless token so do not implement this call if you do not need trustless transfers!
    ///      Implementer should not allow approve() to be executed if there is an overrride
    //       Implemented should return allowance() taking into account override
    function onAllowance(address owner, address spender)
        public
        constant
        returns (uint256 allowanceOverride);
}

contract IEquityTokenController is
    IAgreement,
    ITokenController,
    IETOCommitmentObserver,
    IERC223Callback
{
    /// controls if sender can change old nominee to new nominee
    /// @dev for this to succeed typically a voting of the token holders should happen and new nominee should be set
    function onChangeNominee(address sender, address oldNominee, address newNominee)
        public
        constant
        returns (bool);
}

contract IEquityToken is
    IAgreement,
    IClonedTokenParent,
    IERC223Token,
    ITokenControllerHook
{
    /// @dev equity token is not divisible (Decimals == 0) but single share is represented by
    ///  tokensPerShare tokens
    function tokensPerShare() public constant returns (uint256);

    // number of shares represented by tokens. we round to the closest value.
    function sharesTotalSupply() public constant returns (uint256);

    /// nominal value of a share in decimal(18) precision in currency as per token controller ISHA
    function shareNominalValueUlps() public constant returns (uint256);

    // returns company legal representative account that never changes
    function companyLegalRepresentative() public constant returns (address);

    /// returns current nominee which is contract legal rep
    function nominee() public constant returns (address);

    /// only by previous nominee
    function changeNominee(address newNominee) public;

    /// controlled, always issues to msg.sender
    function issueTokens(uint256 amount) public;

    /// controlled, may send tokens even when transfer are disabled: to active ETO only
    function distributeTokens(address to, uint256 amount) public;

    // controlled, msg.sender is typically failed ETO
    function destroyTokens(uint256 amount) public;
}

// version history as per contract id
// 0 - inital version
// 1 - shareNominalValueUlps added and shareNominalValueEurUlps removed in IEquityToken


contract EquityToken is
    IEquityToken,
    IContractId,
    StandardSnapshotToken,
    Daily,
    TokenMetadata,
    Agreement,
    IsContract,
    Math
{
    ////////////////////////
    // Immutable state
    ////////////////////////

    // reference to platform terms
    uint256 private TOKENS_PER_SHARE;
    // company representative address
    address private COMPANY_LEGAL_REPRESENTATIVE;
    // sets nominal value of a share in share capital currency per ISHA
    uint256 private SHARE_NOMINAL_VALUE_ULPS;

    ////////////////////////
    // Mutable state
    ////////////////////////

    // nominee address
    address private _nominee;
    // company management contract
    IEquityTokenController private _tokenController;

    ////////////////////////
    // Events
    ////////////////////////

    event LogTokensIssued(
        address indexed holder,
        address controller,
        uint256 amount
    );

    event LogTokensDestroyed(
        address indexed holder,
        address controller,
        uint256 amount
    );

    event LogChangeTokenController(
        address oldController,
        address newController,
        address by
    );

    event LogChangeNominee(
        address oldNominee,
        address newNominee,
        address controller,
        address by
    );

    ////////////////////////
    // Modifiers
    ////////////////////////

    modifier onlyIfIssueAllowed(address to, uint256 amount) {
        require(_tokenController.onGenerateTokens(msg.sender, to, amount), "NF_EQTOKEN_NO_GENERATE");
        _;
    }

    modifier onlyIfDestroyAllowed(address owner, uint256 amount) {
        require(_tokenController.onDestroyTokens(msg.sender, owner, amount), "NF_EQTOKEN_NO_DESTROY");
        _;
    }

    ////////////////////////
    // Constructor
    ////////////////////////

    constructor(
        Universe universe,
        IEquityTokenController controller,
        ETOTokenTerms etoTokenTerms,
        address nominee,
        address companyLegalRep
    )
        Agreement(universe.accessPolicy(), universe.forkArbiter())
        StandardSnapshotToken(
            IClonedTokenParent(0x0),
            0
        )
        TokenMetadata(
            etoTokenTerms.EQUITY_TOKEN_NAME(),
            etoTokenTerms.EQUITY_TOKENS_PRECISION(),
            etoTokenTerms.EQUITY_TOKEN_SYMBOL(),
            "1.0"
        )
        Daily(0)
        public
    {
        TOKENS_PER_SHARE = etoTokenTerms.EQUITY_TOKENS_PER_SHARE();
        COMPANY_LEGAL_REPRESENTATIVE = companyLegalRep;
        SHARE_NOMINAL_VALUE_ULPS = etoTokenTerms.SHARE_NOMINAL_VALUE_ULPS();

        _nominee = nominee;
        _tokenController = controller;
    }

    ////////////////////////
    // Public functions
    ////////////////////////

    //
    // Implements IEquityToken
    //

    /// @dev token controller performs access control
    function issueTokens(uint256 amount)
        public
        onlyIfIssueAllowed(address(this), amount)
        acceptAgreement(msg.sender)
    {
        mGenerateTokens(msg.sender, amount);
        emit LogTokensIssued(msg.sender, _tokenController, amount);
    }

    /// differs from transfer only by 'to' accepting agreement
    function distributeTokens(address to, uint256 amount)
        public
        acceptAgreement(to)
    {
        mTransfer(msg.sender, to, amount);
    }

    /// @dev token controller will allow if ETO in refund state
    function destroyTokens(uint256 amount)
        public
        onlyIfDestroyAllowed(msg.sender, amount)
        acceptAgreement(msg.sender)
    {
        mDestroyTokens(msg.sender, amount);
        emit LogTokensDestroyed(msg.sender, _tokenController, amount);
    }

    function changeNominee(address newNominee)
        public
    {
        // typically requires a valid migration in the old controller
        require(_tokenController.onChangeNominee(msg.sender, _nominee, newNominee));
        _nominee = newNominee;
        emit LogChangeNominee(_nominee, newNominee, _tokenController, msg.sender);
    }

    function tokensPerShare() public constant returns (uint256) {
        return TOKENS_PER_SHARE;
    }

    function sharesTotalSupply() public constant returns (uint256) {
        return tokensToShares(totalSupply());
    }

    function shareNominalValueUlps() public constant returns (uint256) {
        return SHARE_NOMINAL_VALUE_ULPS;
    }

    function nominee() public constant returns (address) {
        return _nominee;
    }

    function companyLegalRepresentative() public constant returns (address) {
        return COMPANY_LEGAL_REPRESENTATIVE;
    }

    //
    // Implements ITokenControllerHook
    //

    function changeTokenController(address newController)
        public
    {
        // typically requires a valid migration in the old controller
        require(_tokenController.onChangeTokenController(msg.sender, newController), "NF_ET_NO_PERM_NEW_CONTROLLER");
        _tokenController = IEquityTokenController(newController);
        emit LogChangeTokenController(_tokenController, newController, msg.sender);
    }

    function tokenController() public constant returns (address) {
        return _tokenController;
    }

    //
    // Implements IERC223Token with IERC223Callback (tokenFallback) callback
    //

    function transfer(address to, uint256 amount, bytes data)
        public
        returns (bool)
    {
        // it is necessary to point out implementation to be called
        BasicSnapshotToken.mTransfer(msg.sender, to, amount);

        // Notify the receiving contract.
        if (isContract(to)) {
            IERC223Callback(to).tokenFallback(msg.sender, amount, data);
        }
        return true;
    }

    //
    // Implements IContractId
    //

    function contractId() public pure returns (bytes32 id, uint256 version) {
        return (0x45a709aff6d5ae42cb70f87551d8d7dbec5235cf2baa71a009ed0a9795258d8f, 1);
    }

    ////////////////////////
    // Internal functions
    ////////////////////////

    //
    // Implements MTokenController
    //

    function mOnTransfer(
        address from,
        address to,
        uint256 amount
    )
        internal
        acceptAgreement(from)
        returns (bool allow)
    {
        // if token controller allows transfer
        return _tokenController.onTransfer(msg.sender, from, to, amount);
    }

    function mOnApprove(
        address owner,
        address spender,
        uint256 amount
    )
        internal
        acceptAgreement(owner)
        returns (bool allow)
    {
        return _tokenController.onApprove(owner, spender, amount);
    }

    function mAllowanceOverride(
        address owner,
        address spender
    )
        internal
        constant
        returns (uint256)
    {
        return _tokenController.onAllowance(owner, spender);
    }

    //
    // Overrides Agreement
    //

    function mCanAmend(address legalRepresentative)
        internal
        returns (bool)
    {
        return legalRepresentative == _nominee;
    }

    function tokensToShares(uint256 amount)
        internal
        constant
        returns (uint256)
    {
        return amount / TOKENS_PER_SHARE;
    }
}

Contract Security Audit

Contract ABI

[{"constant":true,"inputs":[{"name":"timestamp","type":"uint256"}],"name":"snapshotAt","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"amount","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newNominee","type":"address"}],"name":"changeNominee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"amount","type":"uint256"}],"name":"distributeTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"nominee","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"},{"name":"snapshotId","type":"uint256"}],"name":"balanceOfAt","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"version","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newPolicy","type":"address"},{"name":"newAccessController","type":"address"}],"name":"setAccessPolicy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"amount","type":"uint256"}],"name":"destroyTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"signatory","type":"address"}],"name":"agreementSignedAtBlock","outputs":[{"name":"blockNo","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"amendmentsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"parentToken","outputs":[{"name":"parent","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"}],"name":"allBalancesOf","outputs":[{"name":"","type":"uint256[2][]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"contractId","outputs":[{"name":"id","type":"bytes32"},{"name":"version","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"amendmentIndex","type":"uint256"}],"name":"pastAgreement","outputs":[{"name":"contractLegalRepresentative","type":"address"},{"name":"signedBlockTimestamp","type":"uint256"},{"name":"agreementUri","type":"string"},{"name":"index","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentSnapshotId","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"snapshotId","type":"uint256"}],"name":"totalSupplyAt","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"amount","type":"uint256"}],"name":"issueTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"parentSnapshotId","outputs":[{"name":"snapshotId","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"sharesTotalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"shareNominalValueUlps","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"amount","type":"uint256"},{"name":"data","type":"bytes"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"currentAgreement","outputs":[{"name":"contractLegalRepresentative","type":"address"},{"name":"signedBlockTimestamp","type":"uint256"},{"name":"agreementUri","type":"string"},{"name":"index","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"amount","type":"uint256"},{"name":"extraData","type":"bytes"}],"name":"approveAndCall","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"tokensPerShare","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newController","type":"address"}],"name":"changeTokenController","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ethereumForkArbiter","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"agreementUri","type":"string"}],"name":"amendAgreement","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"tokenController","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"companyLegalRepresentative","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"accessPolicy","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"universe","type":"address"},{"name":"controller","type":"address"},{"name":"etoTokenTerms","type":"address"},{"name":"nominee","type":"address"},{"name":"companyLegalRep","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"holder","type":"address"},{"indexed":false,"name":"controller","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"LogTokensIssued","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"holder","type":"address"},{"indexed":false,"name":"controller","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"LogTokensDestroyed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"oldController","type":"address"},{"indexed":false,"name":"newController","type":"address"},{"indexed":false,"name":"by","type":"address"}],"name":"LogChangeTokenController","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"oldNominee","type":"address"},{"indexed":false,"name":"newNominee","type":"address"},{"indexed":false,"name":"controller","type":"address"},{"indexed":false,"name":"by","type":"address"}],"name":"LogChangeNominee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"controller","type":"address"},{"indexed":false,"name":"oldPolicy","type":"address"},{"indexed":false,"name":"newPolicy","type":"address"}],"name":"LogAccessPolicyChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"accepter","type":"address"}],"name":"LogAgreementAccepted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"contractLegalRepresentative","type":"address"},{"indexed":false,"name":"agreementUri","type":"string"}],"name":"LogAgreementAmended","type":"event"}]

60806040526dc22e450672894ab6cd8efb11d33f6005553480156200002357600080fd5b5060405160a0806200302283398101604081815282516020808501518386015160608701516080909701517ff5d60a51000000000000000000000000000000000000000000000000000000008752945193969195909491939192600160a060020a0388169263f5d60a519260048082019392918290030181600087803b158015620000ad57600080fd5b505af1158015620000c2573d6000803e3d6000fd5b505050506040513d6020811015620000d957600080fd5b5051604080517f23dc2b570000000000000000000000000000000000000000000000000000000081529051600160a060020a038816916323dc2b579160048083019260209291908290030181600087803b1580156200013757600080fd5b505af11580156200014c573d6000803e3d6000fd5b505050506040513d60208110156200016357600080fd5b5051604080517fc4467b6f00000000000000000000000000000000000000000000000000000000815290518391600160a060020a0388169163c4467b6f9160048082019260009290919082900301818387803b158015620001c357600080fd5b505af1158015620001d8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156200020257600080fd5b8101908080516401000000008111156200021b57600080fd5b820160208101848111156200022f57600080fd5b81516401000000008111828201871017156200024a57600080fd5b505092919050505086600160a060020a03166366448ae86040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015620002aa57600080fd5b505af1158015620002bf573d6000803e3d6000fd5b505050506040513d6020811015620002d657600080fd5b5051604080517f018419440000000000000000000000000000000000000000000000000000000081529051600160a060020a038a1691630184194491600480830192600092919082900301818387803b1580156200033357600080fd5b505af115801562000348573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156200037257600080fd5b8101908080516401000000008111156200038b57600080fd5b820160208101848111156200039f57600080fd5b8151640100000000811182820187101715620003ba57600080fd5b505060408051808201909152600381527f312e300000000000000000000000000000000000000000000000000000000000602082015260008054600160a060020a0319168155919450925090505083516200041d90600690602087019062000621565b5081516200043390600790602085019062000621565b506008805460ff191660ff851617905580516200045890600990602084019062000621565b5050505050600160a060020a03811615156200047357600080fd5b600a8054600160a060020a031916600160a060020a03928316179055811615156200049d57600080fd5b600b8054600160a060020a031916600160a060020a03928316179055604080517f436cdb030000000000000000000000000000000000000000000000000000000081529051918616925063436cdb039160048083019260209291908290030181600087803b1580156200050f57600080fd5b505af115801562000524573d6000803e3d6000fd5b505050506040513d60208110156200053b57600080fd5b5051600e55600f8054600160a060020a031916600160a060020a0383811691909117909155604080517fc46ca0d800000000000000000000000000000000000000000000000000000000815290519185169163c46ca0d8916004808201926020929091908290030181600087803b158015620005b657600080fd5b505af1158015620005cb573d6000803e3d6000fd5b505050506040513d6020811015620005e257600080fd5b50516010555060118054600160a060020a03928316600160a060020a031991821617909155601280549490921693169290921790915550620006c69050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200066457805160ff191683800117855562000694565b8280016001018555821562000694579182015b828111156200069457825182559160200191906001019062000677565b50620006a2929150620006a6565b5090565b620006c391905b80821115620006a25760008155600101620006ad565b90565b61294c80620006d66000396000f3006080604052600436106101c95763ffffffff60e060020a60003504166305ecc08581146101ce57806306fdde03146101f8578063095ea7b3146102825780630cda9983146102ba578063158a4988146102dd57806318160ddd1461030157806320f99c0a1461031657806323b872dd14610347578063313ce567146103715780634ee2cd7e1461039c57806354fd4d50146103c057806357875631146103d557806367fbd289146103fc5780636fa00f071461041457806370a08231146104355780637b1543131461045657806380a540011461046b5780638273a411146104805780638291286c146105125780638fb29d6c1461054057806395d89b41146105f7578063970875ce1461060c578063981b24d014610621578063a5820daa14610639578063a899ef5714610651578063a9059cbb14610666578063abe912711461068a578063b7c582d31461069f578063be45fd62146106b4578063c90f793e1461071d578063cae9ca5114610732578063d5092b561461079b578063d6c8976b146107b0578063dd62ed3e146107d1578063ea490b84146107f8578063eb4e64d61461080d578063eddd9d8214610866578063ef9711981461087b578063f5d60a5114610890575b600080fd5b3480156101da57600080fd5b506101e66004356108a5565b60408051918252519081900360200190f35b34801561020457600080fd5b5061020d6108c5565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561024757818101518382015260200161022f565b50505050905090810190601f1680156102745780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561028e57600080fd5b506102a6600160a060020a036004351660243561095c565b604080519115158252519081900360200190f35b3480156102c657600080fd5b506102db600160a060020a0360043516610a27565b005b3480156102e957600080fd5b506102db600160a060020a0360043516602435610b52565b34801561030d57600080fd5b506101e6610b6c565b34801561032257600080fd5b5061032b610b83565b60408051600160a060020a039092168252519081900360200190f35b34801561035357600080fd5b506102a6600160a060020a0360043581169060243516604435610b92565b34801561037d57600080fd5b50610386610bf8565b6040805160ff9092168252519081900360200190f35b3480156103a857600080fd5b506101e6600160a060020a0360043516602435610c01565b3480156103cc57600080fd5b5061020d610c14565b3480156103e157600080fd5b506102db600160a060020a0360043581169060243516610c75565b34801561040857600080fd5b506102db600435610ed6565b34801561042057600080fd5b506101e6600160a060020a036004351661104a565b34801561044157600080fd5b506101e6600160a060020a0360043516611065565b34801561046257600080fd5b506101e6611078565b34801561047757600080fd5b5061032b61107e565b34801561048c57600080fd5b506104a1600160a060020a036004351661108d565b60405180806020018281038252838181518152602001915080516000925b8184101561050157602080850284010151604080838360005b838110156104f05781810151838201526020016104d8565b5050505090500192600101926104bf565b925050509250505060405180910390f35b34801561051e57600080fd5b50610527611173565b6040805192835260208301919091528051918290030190f35b34801561054c57600080fd5b5061055860043561119a565b6040518085600160a060020a0316600160a060020a0316815260200184815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b838110156105b95781810151838201526020016105a1565b50505050905090810190601f1680156105e65780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b34801561060357600080fd5b5061020d61128f565b34801561061857600080fd5b506101e66112f0565b34801561062d57600080fd5b506101e66004356112fa565b34801561064557600080fd5b506102db600435611305565b34801561065d57600080fd5b506101e6611478565b34801561067257600080fd5b506102a6600160a060020a036004351660243561147e565b34801561069657600080fd5b506101e6611494565b3480156106ab57600080fd5b506101e66114a6565b3480156106c057600080fd5b50604080516020600460443581810135601f81018490048402850184019095528484526102a6948235600160a060020a03169460248035953695946064949201919081908401838280828437509497506114ac9650505050505050565b34801561072957600080fd5b506105586115b7565b34801561073e57600080fd5b50604080516020600460443581810135601f81018490048402850184019095528484526102a6948235600160a060020a03169460248035953695946064949201919081908401838280828437509497506116c79650505050505050565b3480156107a757600080fd5b506101e66117fa565b3480156107bc57600080fd5b506102db600160a060020a0360043516611800565b3480156107dd57600080fd5b506101e6600160a060020a036004358116906024351661197a565b34801561080457600080fd5b5061032b6119ca565b34801561081957600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526102db9436949293602493928401919081908401838280828437509497506119d99650505050505050565b34801561087257600080fd5b5061032b611b95565b34801561088757600080fd5b5061032b611ba4565b34801561089c57600080fd5b5061032b611bb3565b60055460009082106108b657600080fd5b6108bf82611bc2565b92915050565b60068054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109515780601f1061092657610100808354040283529160200191610951565b820191906000526020600020905b81548152906001019060200180831161093457829003601f168201915b505050505090505b90565b6000610969338484611bf6565b151561097457600080fd5b8115806109a25750336000908152600460209081526040808320600160a060020a0387168452909152902054155b80156109b557506109b33384611cae565b155b15156109c057600080fd5b336000818152600460209081526040808320600160a060020a03881680855290835292819020869055805186815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a350600192915050565b601254601154604080517f3eb96f2e000000000000000000000000000000000000000000000000000000008152336004820152600160a060020a039283166024820152848316604482015290519190921691633eb96f2e9160648083019260209291908290030181600087803b158015610aa057600080fd5b505af1158015610ab4573d6000803e3d6000fd5b505050506040513d6020811015610aca57600080fd5b50511515610ad757600080fd5b60118054600160a060020a0380841673ffffffffffffffffffffffffffffffffffffffff1990921682179283905560125460408051948316855260208501939093521682820152336060830152517f695ac7923336642d923d1015896d1adc81d9c8e8f8acbe9593dcbc394c39d05f9181900360800190a150565b81610b5c81611d54565b610b67338484611dc7565b505050565b6000610b7e610b79611f65565b611f70565b905090565b601154600160a060020a031690565b600080610b9f8533611cae565b9050801515610bd55750600160a060020a0384166000908152600460209081526040808320338452909152902080548381039091555b82811015610be257600080fd5b610bed858585611dc7565b506001949350505050565b60085460ff1690565b6000610c0d8383612059565b9392505050565b60098054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109515780601f1061092657610100808354040283529160200191610951565b600a54604080517f9085b77f0000000000000000000000000000000000000000000000000000000081523360048201527fac42f8beb17975ed062dcb80c63e6d203ef1c2c335ced149dc5664cc671cb7da60248201819052306044830152600080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166064840152925192939092600160a060020a0390911691639085b77f91608480830192602092919082900301818887803b158015610d3357600080fd5b505af1158015610d47573d6000803e3d6000fd5b505050506040513d6020811015610d5d57600080fd5b50511515610d6a57600080fd5b604080517f9085b77f000000000000000000000000000000000000000000000000000000008152600160a060020a0385811660048301527fac42f8beb17975ed062dcb80c63e6d203ef1c2c335ced149dc5664cc671cb7da6024830152306044830152600080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166064840152925190871692639085b77f92608480820193602093909283900390910190829087803b158015610e2457600080fd5b505af1158015610e38573d6000803e3d6000fd5b505050506040513d6020811015610e4e57600080fd5b50511515610e5b57600080fd5b600a8054600160a060020a0386811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040805133815291909216602082018190528183019390935290519193507f7d475c32583df95fccc34a6e12df24c1fc9943092cc129b6512013aecba0f136919081900360600190a150505050565b601254604080517f0c36efa000000000000000000000000000000000000000000000000000000000815233600482018190526024820181905260448201859052915191928492600160a060020a0390911691630c36efa09160648083019260209291908290030181600087803b158015610f4f57600080fd5b505af1158015610f63573d6000803e3d6000fd5b505050506040513d6020811015610f7957600080fd5b50511515610fe857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e465f4551544f4b454e5f4e4f5f44455354524f590000000000000000000000604482015290519081900360640190fd5b33610ff281611d54565b610ffc338561216b565b60125460408051600160a060020a03909216825260208201869052805133927f9ef97f43f6ed50e9d783b3bc0a7d4c49e4c3d72cd643a1ccd4698c1584683edf92908290030190a250505050565b600160a060020a03166000908152600d602052604090205490565b60006108bf82611073611f65565b612059565b600c5490565b600054600160a060020a031690565b600160a060020a03811660009081526002602090815260408083208054825181815281850281019094019092526060939092849280156110e757816020015b6110d4612802565b8152602001906001900390816110cc5790505b509150600090505b825481101561116b576040805190810160405280848381548110151561111157fe5b9060005260206000209060020201600001548152602001848381548110151561113657fe5b906000526020600020906002020160010154815250828281518110151561115957fe5b602090810290910101526001016110ef565b509392505050565b7f45a709aff6d5ae42cb70f87551d8d7dbec5235cf2baa71a009ed0a9795258d8f60019091565b6000806060600080600c868154811015156111b157fe5b906000526020600020906003020190508060000160009054906101000a9004600160a060020a031681600101548260020188818054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156112785780601f1061124d57610100808354040283529160200191611278565b820191906000526020600020905b81548152906001019060200180831161125b57829003601f168201915b505050505091509450945094509450509193509193565b60078054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109515780601f1061092657610100808354040283529160200191610951565b6000610b7e611f65565b60006108bf82611f70565b601254604080517f7d31c9f0000000000000000000000000000000000000000000000000000000008152336004820152306024820181905260448201859052915191928492600160a060020a0390911691637d31c9f09160648083019260209291908290030181600087803b15801561137d57600080fd5b505af1158015611391573d6000803e3d6000fd5b505050506040513d60208110156113a757600080fd5b5051151561141657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4e465f4551544f4b454e5f4e4f5f47454e455241544500000000000000000000604482015290519081900360640190fd5b3361142081611d54565b61142a33856122bc565b60125460408051600160a060020a03909216825260208201869052805133927fe1d005ce03271afee8eb8f3366ca27942bedc8c4be0e488f34b464524b59f82492908290030190a250505050565b60015490565b600061148b338484611dc7565b50600192915050565b6000610b7e6114a1610b6c565b612421565b60105490565b60006114b9338585611dc7565b6114c284612437565b156115ad5783600160a060020a031663c0ee0b8a3385856040518463ffffffff1660e060020a0281526004018084600160a060020a0316600160a060020a0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561154657818101518382015260200161152e565b50505050905090810190601f1680156115735780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561159457600080fd5b505af11580156115a8573d6000803e3d6000fd5b505050505b5060019392505050565b6000806060600080600080600c805490501115156115d457600080fd5b600c805460001981019350839081106115e957fe5b906000526020600020906003020190508060000160009054906101000a9004600160a060020a031681600101548260020184818054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156116b05780601f10611685576101008083540402835291602001916116b0565b820191906000526020600020905b81548152906001019060200180831161169357829003601f168201915b505050505091509550955095509550505090919293565b60006116d3848461095c565b15156116de57600080fd5b6040517f8f4ffcb10000000000000000000000000000000000000000000000000000000081523360048201818152602483018690523060448401819052608060648501908152865160848601528651600160a060020a038a1695638f4ffcb195948a94938a939192909160a490910190602085019080838360005b83811015611771578181015183820152602001611759565b50505050905090810190601f16801561179e5780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b1580156117c057600080fd5b505af11580156117d4573d6000803e3d6000fd5b505050506040513d60208110156117ea57600080fd5b505190508015156115ad57600080fd5b600e5490565b601254604080517f307e6661000000000000000000000000000000000000000000000000000000008152336004820152600160a060020a0384811660248301529151919092169163307e66619160448083019260209291908290030181600087803b15801561186e57600080fd5b505af1158015611882573d6000803e3d6000fd5b505050506040513d602081101561189857600080fd5b5051151561190757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4e465f45545f4e4f5f5045524d5f4e45575f434f4e54524f4c4c455200000000604482015290519081900360640190fd5b60128054600160a060020a0380841673ffffffffffffffffffffffffffffffffffffffff199092168217928390556040805193909116835260208301919091523382820152517fb8a1f6190887ec2747b0a5d8d1bfc22e005c91c707ce9f3574470735cea727119181900360600190a150565b6000806119878484611cae565b9050600081111561199a578091506119c3565b600160a060020a0380851660009081526004602090815260408083209387168352929052205491505b5092915050565b600b54600160a060020a031690565b6119e161281d565b336119eb8161243f565b15156119f657600080fd5b60408051606081018252338152426020808301918252928201868152600c80546001810180835560009290925284517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c76003909202918201805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0390921691909117815593517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c88201559151805194975090948794611ad9937fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c901929091019061283c565b505050507fe9835ee18f0f0b190604da3474d67a8f29aba2c92e90eee2bdaeca67d40d5a6b33846040518083600160a060020a0316600160a060020a0316815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611b55578181015183820152602001611b3d565b50505050905090810190601f168015611b825780820380516001836020036101000a031916815260200191505b50935050505060405180910390a1505050565b601254600160a060020a031690565b600f54600160a060020a031690565b600a54600160a060020a031690565b6000620151806fffffffffffffffffffffffffffffffff831604700100000000000000000000000000000000029050919050565b600083611c0281611d54565b601254604080517fda682aeb000000000000000000000000000000000000000000000000000000008152600160a060020a0388811660048301528781166024830152604482018790529151919092169163da682aeb9160648083019260209291908290030181600087803b158015611c7957600080fd5b505af1158015611c8d573d6000803e3d6000fd5b505050506040513d6020811015611ca357600080fd5b505195945050505050565b601254604080517fc00d752c000000000000000000000000000000000000000000000000000000008152600160a060020a03858116600483015284811660248301529151600093929092169163c00d752c9160448082019260209290919082900301818787803b158015611d2157600080fd5b505af1158015611d35573d6000803e3d6000fd5b505050506040513d6020811015611d4b57600080fd5b50519392505050565b600160a060020a0381166000908152600d60205260409020541515611dc457600c54600010611d8257600080fd5b600160a060020a0381166000818152600d6020526040808220439055517f8c41d101e4d957423a65fda82dcc88bc6b3e756166d2331f663c10166658ebb89190a25b50565b6000808080600160a060020a0386161515611de157600080fd5b6000611deb61107e565b600160a060020a03161480611e765750611e0361107e565b600160a060020a031663970875ce6040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015611e4057600080fd5b505af1158015611e54573d6000803e3d6000fd5b505050506040513d6020811015611e6a57600080fd5b5051611e74611478565b105b1515611e8157600080fd5b611e8c878787612453565b1515611e9757600080fd5b611ea087611065565b935084841015611eaf57600080fd5b600160a060020a03871660009081526002602052604090208585039350611ed690846124dc565b611edf86611065565b91505083810181811015611eef57fe5b600160a060020a0386166000908152600260205260409020611f1190826124dc565b85600160a060020a031687600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef876040518082815260200191505060405180910390a350505050505050565b6000610b7e42611bc2565b6000600381611f7f8285612678565b15611f9757611f90828560006126c6565b9250612052565b600054600160a060020a03161561204d578360015411611fb957600154611fbb565b835b90506000809054906101000a9004600160a060020a0316600160a060020a031663981b24d0826040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b15801561201a57600080fd5b505af115801561202e573d6000803e3d6000fd5b505050506040513d602081101561204457600080fd5b50519250612052565b600092505b5050919050565b600160a060020a03821660009081526002602052604081208161207c8285612678565b156120945761208d828560006126c6565b9250612163565b600054600160a060020a03161561215e5783600154116120b6576001546120b8565b835b60008054604080517f4ee2cd7e000000000000000000000000000000000000000000000000000000008152600160a060020a038a81166004830152602482018690529151949550911692634ee2cd7e92604480840193602093929083900390910190829087803b15801561212b57600080fd5b505af115801561213f573d6000803e3d6000fd5b505050506040513d602081101561215557600080fd5b50519250612163565b600092505b505092915050565b60008080808061217961107e565b600160a060020a03161480612204575061219161107e565b600160a060020a031663970875ce6040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156121ce57600080fd5b505af11580156121e2573d6000803e3d6000fd5b505050506040513d60208110156121f857600080fd5b5051612202611478565b105b151561220f57600080fd5b612217610b6c565b93508484101561222657600080fd5b61222f86611065565b92508483101561223e57600080fd5b50508282038382036122516003836124dc565b600160a060020a038616600090815260026020526040902061227390826124dc565b604080518681529051600091600160a060020a038916917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050505050565b6000808080600160a060020a03861615156122d657600080fd5b60006122e061107e565b600160a060020a0316148061236b57506122f861107e565b600160a060020a031663970875ce6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561233557600080fd5b505af1158015612349573d6000803e3d6000fd5b505050506040513d602081101561235f57600080fd5b5051612369611478565b105b151561237657600080fd5b61237e610b6c565b935084840192508383101561239257600080fd5b61239b86611065565b915050838101818110156123ab57fe5b6123b66003846124dc565b600160a060020a03861660009081526002602052604090206123d890826124dc565b604080518681529051600160a060020a038816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050505050565b6000600e548281151561243057fe5b0492915050565b6000903b1190565b601154600160a060020a0390811691161490565b60008361245f81611d54565b601254604080517f0987df03000000000000000000000000000000000000000000000000000000008152336004820152600160a060020a03888116602483015287811660448301526064820187905291519190921691630987df039160848083019260209291908290030181600087803b158015611c7957600080fd5b6000806000806000806124ed6112f0565b88549096501594508415612538576040805180820190915286815260208082018981528a5460018181018d5560008d815293909320935160029091029093019283555191015561266e565b875460001981019450869089908690811061254f57fe5b90600052602060002090600202016000015410925082156125d65786888581548110151561257957fe5b90600052602060002090600202016001015414915081156125995761266e565b6040805180820190915286815260208082018981528a5460018181018d5560008d815293909320935160029091029093019283555191015561266e565b60008411801561260757508688600186038154811015156125f357fe5b906000526020600020906002020160010154145b9050801561264957878481548110151561261d57fe5b6000918252602082206002909102018181556001015587546126438960001983016128ba565b5061266e565b86888581548110151561265857fe5b9060005260206000209060020201600101819055505b5050505050505050565b6000612682611f65565b82111561268e57600080fd5b82546000108015610c0d5750818360008154811015156126aa57fe5b9060005260206000209060020201600001541115905092915050565b60008060008060008060006126d9611f65565b8911156126e557600080fd5b895415156126f5578796506127f5565b8954600019810196508a908790811061270a57fe5b6000918252602090912060029091020154945084891061274b57898681548110151561273257fe5b90600052602060002090600202016001015496506127f5565b89600081548110151561275a57fe5b90600052602060002090600202016000015493508389101561277e578796506127f5565b600092508591505b828211156127d2576002600183850101049050888a828154811015156127a857fe5b6000918252602090912060029091020154116127c6578092506127cd565b6001810391505b612786565b89838154811015156127e057fe5b90600052602060002090600202016001015496505b5050505050509392505050565b60408051808201825290600290829080388339509192915050565b6040805160608181018352600080835260208301529181019190915290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061287d57805160ff19168380011785556128aa565b828001600101855582156128aa579182015b828111156128aa57825182559160200191906001019061288f565b506128b69291506128e6565b5090565b815481835581811115610b6757600202816002028360005260206000209182019101610b679190612900565b61095991905b808211156128b657600081556001016128ec565b61095991905b808211156128b657600080825560018201556002016129065600a165627a7a723058205e4fe0c7a1712aa620306235bb48f56ebc5ca7e487a50a84fcace70d907d3330002900000000000000000000000082fb5126506b6c315fa4a7ae3d4cb8a46a1aae670000000000000000000000001c4b7282cce720cb184c3365bb6b9f75e332bdd80000000000000000000000006417642df53244d544762cc2b87e1082cdff1070000000000000000000000000f3f35c09a8e9de32a8d60451bd80e5381cd8f52d000000000000000000000000b8a93fdc69df45c59302fe867877786a5e05be05

Deployed Bytecode

0x6080604052600436106101c95763ffffffff60e060020a60003504166305ecc08581146101ce57806306fdde03146101f8578063095ea7b3146102825780630cda9983146102ba578063158a4988146102dd57806318160ddd1461030157806320f99c0a1461031657806323b872dd14610347578063313ce567146103715780634ee2cd7e1461039c57806354fd4d50146103c057806357875631146103d557806367fbd289146103fc5780636fa00f071461041457806370a08231146104355780637b1543131461045657806380a540011461046b5780638273a411146104805780638291286c146105125780638fb29d6c1461054057806395d89b41146105f7578063970875ce1461060c578063981b24d014610621578063a5820daa14610639578063a899ef5714610651578063a9059cbb14610666578063abe912711461068a578063b7c582d31461069f578063be45fd62146106b4578063c90f793e1461071d578063cae9ca5114610732578063d5092b561461079b578063d6c8976b146107b0578063dd62ed3e146107d1578063ea490b84146107f8578063eb4e64d61461080d578063eddd9d8214610866578063ef9711981461087b578063f5d60a5114610890575b600080fd5b3480156101da57600080fd5b506101e66004356108a5565b60408051918252519081900360200190f35b34801561020457600080fd5b5061020d6108c5565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561024757818101518382015260200161022f565b50505050905090810190601f1680156102745780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561028e57600080fd5b506102a6600160a060020a036004351660243561095c565b604080519115158252519081900360200190f35b3480156102c657600080fd5b506102db600160a060020a0360043516610a27565b005b3480156102e957600080fd5b506102db600160a060020a0360043516602435610b52565b34801561030d57600080fd5b506101e6610b6c565b34801561032257600080fd5b5061032b610b83565b60408051600160a060020a039092168252519081900360200190f35b34801561035357600080fd5b506102a6600160a060020a0360043581169060243516604435610b92565b34801561037d57600080fd5b50610386610bf8565b6040805160ff9092168252519081900360200190f35b3480156103a857600080fd5b506101e6600160a060020a0360043516602435610c01565b3480156103cc57600080fd5b5061020d610c14565b3480156103e157600080fd5b506102db600160a060020a0360043581169060243516610c75565b34801561040857600080fd5b506102db600435610ed6565b34801561042057600080fd5b506101e6600160a060020a036004351661104a565b34801561044157600080fd5b506101e6600160a060020a0360043516611065565b34801561046257600080fd5b506101e6611078565b34801561047757600080fd5b5061032b61107e565b34801561048c57600080fd5b506104a1600160a060020a036004351661108d565b60405180806020018281038252838181518152602001915080516000925b8184101561050157602080850284010151604080838360005b838110156104f05781810151838201526020016104d8565b5050505090500192600101926104bf565b925050509250505060405180910390f35b34801561051e57600080fd5b50610527611173565b6040805192835260208301919091528051918290030190f35b34801561054c57600080fd5b5061055860043561119a565b6040518085600160a060020a0316600160a060020a0316815260200184815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b838110156105b95781810151838201526020016105a1565b50505050905090810190601f1680156105e65780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b34801561060357600080fd5b5061020d61128f565b34801561061857600080fd5b506101e66112f0565b34801561062d57600080fd5b506101e66004356112fa565b34801561064557600080fd5b506102db600435611305565b34801561065d57600080fd5b506101e6611478565b34801561067257600080fd5b506102a6600160a060020a036004351660243561147e565b34801561069657600080fd5b506101e6611494565b3480156106ab57600080fd5b506101e66114a6565b3480156106c057600080fd5b50604080516020600460443581810135601f81018490048402850184019095528484526102a6948235600160a060020a03169460248035953695946064949201919081908401838280828437509497506114ac9650505050505050565b34801561072957600080fd5b506105586115b7565b34801561073e57600080fd5b50604080516020600460443581810135601f81018490048402850184019095528484526102a6948235600160a060020a03169460248035953695946064949201919081908401838280828437509497506116c79650505050505050565b3480156107a757600080fd5b506101e66117fa565b3480156107bc57600080fd5b506102db600160a060020a0360043516611800565b3480156107dd57600080fd5b506101e6600160a060020a036004358116906024351661197a565b34801561080457600080fd5b5061032b6119ca565b34801561081957600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526102db9436949293602493928401919081908401838280828437509497506119d99650505050505050565b34801561087257600080fd5b5061032b611b95565b34801561088757600080fd5b5061032b611ba4565b34801561089c57600080fd5b5061032b611bb3565b60055460009082106108b657600080fd5b6108bf82611bc2565b92915050565b60068054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109515780601f1061092657610100808354040283529160200191610951565b820191906000526020600020905b81548152906001019060200180831161093457829003601f168201915b505050505090505b90565b6000610969338484611bf6565b151561097457600080fd5b8115806109a25750336000908152600460209081526040808320600160a060020a0387168452909152902054155b80156109b557506109b33384611cae565b155b15156109c057600080fd5b336000818152600460209081526040808320600160a060020a03881680855290835292819020869055805186815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a350600192915050565b601254601154604080517f3eb96f2e000000000000000000000000000000000000000000000000000000008152336004820152600160a060020a039283166024820152848316604482015290519190921691633eb96f2e9160648083019260209291908290030181600087803b158015610aa057600080fd5b505af1158015610ab4573d6000803e3d6000fd5b505050506040513d6020811015610aca57600080fd5b50511515610ad757600080fd5b60118054600160a060020a0380841673ffffffffffffffffffffffffffffffffffffffff1990921682179283905560125460408051948316855260208501939093521682820152336060830152517f695ac7923336642d923d1015896d1adc81d9c8e8f8acbe9593dcbc394c39d05f9181900360800190a150565b81610b5c81611d54565b610b67338484611dc7565b505050565b6000610b7e610b79611f65565b611f70565b905090565b601154600160a060020a031690565b600080610b9f8533611cae565b9050801515610bd55750600160a060020a0384166000908152600460209081526040808320338452909152902080548381039091555b82811015610be257600080fd5b610bed858585611dc7565b506001949350505050565b60085460ff1690565b6000610c0d8383612059565b9392505050565b60098054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109515780601f1061092657610100808354040283529160200191610951565b600a54604080517f9085b77f0000000000000000000000000000000000000000000000000000000081523360048201527fac42f8beb17975ed062dcb80c63e6d203ef1c2c335ced149dc5664cc671cb7da60248201819052306044830152600080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166064840152925192939092600160a060020a0390911691639085b77f91608480830192602092919082900301818887803b158015610d3357600080fd5b505af1158015610d47573d6000803e3d6000fd5b505050506040513d6020811015610d5d57600080fd5b50511515610d6a57600080fd5b604080517f9085b77f000000000000000000000000000000000000000000000000000000008152600160a060020a0385811660048301527fac42f8beb17975ed062dcb80c63e6d203ef1c2c335ced149dc5664cc671cb7da6024830152306044830152600080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166064840152925190871692639085b77f92608480820193602093909283900390910190829087803b158015610e2457600080fd5b505af1158015610e38573d6000803e3d6000fd5b505050506040513d6020811015610e4e57600080fd5b50511515610e5b57600080fd5b600a8054600160a060020a0386811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040805133815291909216602082018190528183019390935290519193507f7d475c32583df95fccc34a6e12df24c1fc9943092cc129b6512013aecba0f136919081900360600190a150505050565b601254604080517f0c36efa000000000000000000000000000000000000000000000000000000000815233600482018190526024820181905260448201859052915191928492600160a060020a0390911691630c36efa09160648083019260209291908290030181600087803b158015610f4f57600080fd5b505af1158015610f63573d6000803e3d6000fd5b505050506040513d6020811015610f7957600080fd5b50511515610fe857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e465f4551544f4b454e5f4e4f5f44455354524f590000000000000000000000604482015290519081900360640190fd5b33610ff281611d54565b610ffc338561216b565b60125460408051600160a060020a03909216825260208201869052805133927f9ef97f43f6ed50e9d783b3bc0a7d4c49e4c3d72cd643a1ccd4698c1584683edf92908290030190a250505050565b600160a060020a03166000908152600d602052604090205490565b60006108bf82611073611f65565b612059565b600c5490565b600054600160a060020a031690565b600160a060020a03811660009081526002602090815260408083208054825181815281850281019094019092526060939092849280156110e757816020015b6110d4612802565b8152602001906001900390816110cc5790505b509150600090505b825481101561116b576040805190810160405280848381548110151561111157fe5b9060005260206000209060020201600001548152602001848381548110151561113657fe5b906000526020600020906002020160010154815250828281518110151561115957fe5b602090810290910101526001016110ef565b509392505050565b7f45a709aff6d5ae42cb70f87551d8d7dbec5235cf2baa71a009ed0a9795258d8f60019091565b6000806060600080600c868154811015156111b157fe5b906000526020600020906003020190508060000160009054906101000a9004600160a060020a031681600101548260020188818054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156112785780601f1061124d57610100808354040283529160200191611278565b820191906000526020600020905b81548152906001019060200180831161125b57829003601f168201915b505050505091509450945094509450509193509193565b60078054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109515780601f1061092657610100808354040283529160200191610951565b6000610b7e611f65565b60006108bf82611f70565b601254604080517f7d31c9f0000000000000000000000000000000000000000000000000000000008152336004820152306024820181905260448201859052915191928492600160a060020a0390911691637d31c9f09160648083019260209291908290030181600087803b15801561137d57600080fd5b505af1158015611391573d6000803e3d6000fd5b505050506040513d60208110156113a757600080fd5b5051151561141657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4e465f4551544f4b454e5f4e4f5f47454e455241544500000000000000000000604482015290519081900360640190fd5b3361142081611d54565b61142a33856122bc565b60125460408051600160a060020a03909216825260208201869052805133927fe1d005ce03271afee8eb8f3366ca27942bedc8c4be0e488f34b464524b59f82492908290030190a250505050565b60015490565b600061148b338484611dc7565b50600192915050565b6000610b7e6114a1610b6c565b612421565b60105490565b60006114b9338585611dc7565b6114c284612437565b156115ad5783600160a060020a031663c0ee0b8a3385856040518463ffffffff1660e060020a0281526004018084600160a060020a0316600160a060020a0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561154657818101518382015260200161152e565b50505050905090810190601f1680156115735780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561159457600080fd5b505af11580156115a8573d6000803e3d6000fd5b505050505b5060019392505050565b6000806060600080600080600c805490501115156115d457600080fd5b600c805460001981019350839081106115e957fe5b906000526020600020906003020190508060000160009054906101000a9004600160a060020a031681600101548260020184818054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156116b05780601f10611685576101008083540402835291602001916116b0565b820191906000526020600020905b81548152906001019060200180831161169357829003601f168201915b505050505091509550955095509550505090919293565b60006116d3848461095c565b15156116de57600080fd5b6040517f8f4ffcb10000000000000000000000000000000000000000000000000000000081523360048201818152602483018690523060448401819052608060648501908152865160848601528651600160a060020a038a1695638f4ffcb195948a94938a939192909160a490910190602085019080838360005b83811015611771578181015183820152602001611759565b50505050905090810190601f16801561179e5780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b1580156117c057600080fd5b505af11580156117d4573d6000803e3d6000fd5b505050506040513d60208110156117ea57600080fd5b505190508015156115ad57600080fd5b600e5490565b601254604080517f307e6661000000000000000000000000000000000000000000000000000000008152336004820152600160a060020a0384811660248301529151919092169163307e66619160448083019260209291908290030181600087803b15801561186e57600080fd5b505af1158015611882573d6000803e3d6000fd5b505050506040513d602081101561189857600080fd5b5051151561190757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4e465f45545f4e4f5f5045524d5f4e45575f434f4e54524f4c4c455200000000604482015290519081900360640190fd5b60128054600160a060020a0380841673ffffffffffffffffffffffffffffffffffffffff199092168217928390556040805193909116835260208301919091523382820152517fb8a1f6190887ec2747b0a5d8d1bfc22e005c91c707ce9f3574470735cea727119181900360600190a150565b6000806119878484611cae565b9050600081111561199a578091506119c3565b600160a060020a0380851660009081526004602090815260408083209387168352929052205491505b5092915050565b600b54600160a060020a031690565b6119e161281d565b336119eb8161243f565b15156119f657600080fd5b60408051606081018252338152426020808301918252928201868152600c80546001810180835560009290925284517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c76003909202918201805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0390921691909117815593517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c88201559151805194975090948794611ad9937fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c901929091019061283c565b505050507fe9835ee18f0f0b190604da3474d67a8f29aba2c92e90eee2bdaeca67d40d5a6b33846040518083600160a060020a0316600160a060020a0316815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611b55578181015183820152602001611b3d565b50505050905090810190601f168015611b825780820380516001836020036101000a031916815260200191505b50935050505060405180910390a1505050565b601254600160a060020a031690565b600f54600160a060020a031690565b600a54600160a060020a031690565b6000620151806fffffffffffffffffffffffffffffffff831604700100000000000000000000000000000000029050919050565b600083611c0281611d54565b601254604080517fda682aeb000000000000000000000000000000000000000000000000000000008152600160a060020a0388811660048301528781166024830152604482018790529151919092169163da682aeb9160648083019260209291908290030181600087803b158015611c7957600080fd5b505af1158015611c8d573d6000803e3d6000fd5b505050506040513d6020811015611ca357600080fd5b505195945050505050565b601254604080517fc00d752c000000000000000000000000000000000000000000000000000000008152600160a060020a03858116600483015284811660248301529151600093929092169163c00d752c9160448082019260209290919082900301818787803b158015611d2157600080fd5b505af1158015611d35573d6000803e3d6000fd5b505050506040513d6020811015611d4b57600080fd5b50519392505050565b600160a060020a0381166000908152600d60205260409020541515611dc457600c54600010611d8257600080fd5b600160a060020a0381166000818152600d6020526040808220439055517f8c41d101e4d957423a65fda82dcc88bc6b3e756166d2331f663c10166658ebb89190a25b50565b6000808080600160a060020a0386161515611de157600080fd5b6000611deb61107e565b600160a060020a03161480611e765750611e0361107e565b600160a060020a031663970875ce6040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015611e4057600080fd5b505af1158015611e54573d6000803e3d6000fd5b505050506040513d6020811015611e6a57600080fd5b5051611e74611478565b105b1515611e8157600080fd5b611e8c878787612453565b1515611e9757600080fd5b611ea087611065565b935084841015611eaf57600080fd5b600160a060020a03871660009081526002602052604090208585039350611ed690846124dc565b611edf86611065565b91505083810181811015611eef57fe5b600160a060020a0386166000908152600260205260409020611f1190826124dc565b85600160a060020a031687600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef876040518082815260200191505060405180910390a350505050505050565b6000610b7e42611bc2565b6000600381611f7f8285612678565b15611f9757611f90828560006126c6565b9250612052565b600054600160a060020a03161561204d578360015411611fb957600154611fbb565b835b90506000809054906101000a9004600160a060020a0316600160a060020a031663981b24d0826040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b15801561201a57600080fd5b505af115801561202e573d6000803e3d6000fd5b505050506040513d602081101561204457600080fd5b50519250612052565b600092505b5050919050565b600160a060020a03821660009081526002602052604081208161207c8285612678565b156120945761208d828560006126c6565b9250612163565b600054600160a060020a03161561215e5783600154116120b6576001546120b8565b835b60008054604080517f4ee2cd7e000000000000000000000000000000000000000000000000000000008152600160a060020a038a81166004830152602482018690529151949550911692634ee2cd7e92604480840193602093929083900390910190829087803b15801561212b57600080fd5b505af115801561213f573d6000803e3d6000fd5b505050506040513d602081101561215557600080fd5b50519250612163565b600092505b505092915050565b60008080808061217961107e565b600160a060020a03161480612204575061219161107e565b600160a060020a031663970875ce6040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156121ce57600080fd5b505af11580156121e2573d6000803e3d6000fd5b505050506040513d60208110156121f857600080fd5b5051612202611478565b105b151561220f57600080fd5b612217610b6c565b93508484101561222657600080fd5b61222f86611065565b92508483101561223e57600080fd5b50508282038382036122516003836124dc565b600160a060020a038616600090815260026020526040902061227390826124dc565b604080518681529051600091600160a060020a038916917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050505050565b6000808080600160a060020a03861615156122d657600080fd5b60006122e061107e565b600160a060020a0316148061236b57506122f861107e565b600160a060020a031663970875ce6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561233557600080fd5b505af1158015612349573d6000803e3d6000fd5b505050506040513d602081101561235f57600080fd5b5051612369611478565b105b151561237657600080fd5b61237e610b6c565b935084840192508383101561239257600080fd5b61239b86611065565b915050838101818110156123ab57fe5b6123b66003846124dc565b600160a060020a03861660009081526002602052604090206123d890826124dc565b604080518681529051600160a060020a038816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050505050565b6000600e548281151561243057fe5b0492915050565b6000903b1190565b601154600160a060020a0390811691161490565b60008361245f81611d54565b601254604080517f0987df03000000000000000000000000000000000000000000000000000000008152336004820152600160a060020a03888116602483015287811660448301526064820187905291519190921691630987df039160848083019260209291908290030181600087803b158015611c7957600080fd5b6000806000806000806124ed6112f0565b88549096501594508415612538576040805180820190915286815260208082018981528a5460018181018d5560008d815293909320935160029091029093019283555191015561266e565b875460001981019450869089908690811061254f57fe5b90600052602060002090600202016000015410925082156125d65786888581548110151561257957fe5b90600052602060002090600202016001015414915081156125995761266e565b6040805180820190915286815260208082018981528a5460018181018d5560008d815293909320935160029091029093019283555191015561266e565b60008411801561260757508688600186038154811015156125f357fe5b906000526020600020906002020160010154145b9050801561264957878481548110151561261d57fe5b6000918252602082206002909102018181556001015587546126438960001983016128ba565b5061266e565b86888581548110151561265857fe5b9060005260206000209060020201600101819055505b5050505050505050565b6000612682611f65565b82111561268e57600080fd5b82546000108015610c0d5750818360008154811015156126aa57fe5b9060005260206000209060020201600001541115905092915050565b60008060008060008060006126d9611f65565b8911156126e557600080fd5b895415156126f5578796506127f5565b8954600019810196508a908790811061270a57fe5b6000918252602090912060029091020154945084891061274b57898681548110151561273257fe5b90600052602060002090600202016001015496506127f5565b89600081548110151561275a57fe5b90600052602060002090600202016000015493508389101561277e578796506127f5565b600092508591505b828211156127d2576002600183850101049050888a828154811015156127a857fe5b6000918252602090912060029091020154116127c6578092506127cd565b6001810391505b612786565b89838154811015156127e057fe5b90600052602060002090600202016001015496505b5050505050509392505050565b60408051808201825290600290829080388339509192915050565b6040805160608181018352600080835260208301529181019190915290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061287d57805160ff19168380011785556128aa565b828001600101855582156128aa579182015b828111156128aa57825182559160200191906001019061288f565b506128b69291506128e6565b5090565b815481835581811115610b6757600202816002028360005260206000209182019101610b679190612900565b61095991905b808211156128b657600081556001016128ec565b61095991905b808211156128b657600080825560018201556002016129065600a165627a7a723058205e4fe0c7a1712aa620306235bb48f56ebc5ca7e487a50a84fcace70d907d33300029

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

00000000000000000000000082fb5126506b6c315fa4a7ae3d4cb8a46a1aae670000000000000000000000001c4b7282cce720cb184c3365bb6b9f75e332bdd80000000000000000000000006417642df53244d544762cc2b87e1082cdff1070000000000000000000000000f3f35c09a8e9de32a8d60451bd80e5381cd8f52d000000000000000000000000b8a93fdc69df45c59302fe867877786a5e05be05

-----Decoded View---------------
Arg [0] : universe (address): 0x82FB5126506b6c315FA4a7aE3d4CB8A46A1AAe67
Arg [1] : controller (address): 0x1c4B7282cce720Cb184c3365Bb6B9f75e332bDd8
Arg [2] : etoTokenTerms (address): 0x6417642dF53244d544762cC2b87E1082Cdff1070
Arg [3] : nominee (address): 0xf3f35C09A8e9dE32A8D60451BD80E5381Cd8F52d
Arg [4] : companyLegalRep (address): 0xB8a93FDC69Df45c59302FE867877786A5e05bE05

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 00000000000000000000000082fb5126506b6c315fa4a7ae3d4cb8a46a1aae67
Arg [1] : 0000000000000000000000001c4b7282cce720cb184c3365bb6b9f75e332bdd8
Arg [2] : 0000000000000000000000006417642df53244d544762cc2b87e1082cdff1070
Arg [3] : 000000000000000000000000f3f35c09a8e9de32a8d60451bd80e5381cd8f52d
Arg [4] : 000000000000000000000000b8a93fdc69df45c59302fe867877786a5e05be05


Deployed Bytecode Sourcemap

128203:7488:0:-;;;;;;;;;-1:-1:-1;;;128203:7488:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33720:205;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;33720:205:0;;;;;;;;;;;;;;;;;;;;;36473:111;;8:9:-1;5:2;;;30:1;27;20:12;5:2;36473:111:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;36473:111:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45706:793;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;45706:793:0;-1:-1:-1;;;;;45706:793:0;;;;;;;;;;;;;;;;;;;;;;;;;132057:345;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;132057:345:0;-1:-1:-1;;;;;132057:345:0;;;;;;;131548:156;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;131548:156:0;-1:-1:-1;;;;;131548:156:0;;;;;;;59453:158;;8:9:-1;5:2;;;30:1;27;20:12;5:2;59453:158:0;;;;132771:87;;8:9:-1;5:2;;;30:1;27;20:12;5:2;132771:87:0;;;;;;;;-1:-1:-1;;;;;132771:87:0;;;;;;;;;;;;;;46881:596;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;46881:596:0;-1:-1:-1;;;;;46881:596:0;;;;;;;;;;;;36715:118;;8:9:-1;5:2;;;30:1;27;20:12;5:2;36715:118:0;;;;;;;;;;;;;;;;;;;;;;;60601:186;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;60601:186:0;-1:-1:-1;;;;;60601:186:0;;;;;;;36841:117;;8:9:-1;5:2;;;30:1;27;20:12;5:2;36841:117:0;;;;4174:656;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;4174:656:0;-1:-1:-1;;;;;4174:656:0;;;;;;;;;;131777:272;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;131777:272:0;;;;;16984:174;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;16984:174:0;-1:-1:-1;;;;;16984:174:0;;;;;59748:182;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;59748:182:0;-1:-1:-1;;;;;59748:182:0;;;;;17166:137;;8:9:-1;5:2;;;30:1;27;20:12;5:2;17166:137:0;;;;61000:144;;8:9:-1;5:2;;;30:1;27;20:12;5:2;61000:144:0;;;;61563:719;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;61563:719:0;-1:-1:-1;;;;;61563:719:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;61563:719:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;134181:169;;8:9:-1;5:2;;;30:1;27;20:12;5:2;134181:169:0;;;;;;;;;;;;;;;;;;;;;;;;;;;16423:553;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;16423:553:0;;;;;;;;;;-1:-1:-1;;;;;16423:553:0;-1:-1:-1;;;;;16423:553:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;16423:553:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36592:115;;8:9:-1;5:2;;;30:1;27;20:12;5:2;36592:115:0;;;;60795:141;;8:9:-1;5:2;;;30:1;27;20:12;5:2;60795:141:0;;;;60426:167;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;60426:167:0;;;;;131207:269;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;131207:269:0;;;;;61225:148;;8:9:-1;5:2;;;30:1;27;20:12;5:2;61225:148:0;;;;60192:173;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;60192:173:0;-1:-1:-1;;;;;60192:173:0;;;;;;;132520:118;;8:9:-1;5:2;;;30:1;27;20:12;5:2;132520:118:0;;;;132646:117;;8:9:-1;5:2;;;30:1;27;20:12;5:2;132646:117:0;;;;133698:426;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;133698:426:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;133698:426:0;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;133698:426:0;;-1:-1:-1;133698:426:0;;-1:-1:-1;;;;;;;133698:426:0;15811:604;;8:9:-1;5:2;;;30:1;27;20:12;5:2;15811:604:0;;;;48051:427;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;48051:427:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;48051:427:0;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;48051:427:0;;-1:-1:-1;48051:427:0;;-1:-1:-1;;;;;;;48051:427:0;132410:102;;8:9:-1;5:2;;;30:1;27;20:12;5:2;132410:102:0;;;;133058:425;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;133058:425:0;-1:-1:-1;;;;;133058:425:0;;;;;44938:311;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;44938:311:0;-1:-1:-1;;;;;44938:311:0;;;;;;;;;;15646:157;;8:9:-1;5:2;;;30:1;27;20:12;5:2;15646:157:0;;;;15199:439;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;15199:439:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;15199:439:0;;-1:-1:-1;15199:439:0;;-1:-1:-1;;;;;;;15199:439:0;133491:103;;8:9:-1;5:2;;;30:1;27;20:12;5:2;133491:103:0;;;;132866:126;;8:9:-1;5:2;;;30:1;27;20:12;5:2;132866:126:0;;;;4838:135;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4838:135:0;;;;33720:205;33856:13;;33811:7;;33844:25;;33836:34;;;;;;33890:27;33906:9;33890:7;:27::i;:::-;33883:34;33720:205;-1:-1:-1;;33720:205:0:o;36473:111::-;36572:4;36565:11;;;;;;;;-1:-1:-1;;36565:11:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36541:6;;36565:11;;36572:4;;36565:11;;36572:4;36565:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36473:111;;:::o;45706:793::-;45790:12;45897:39;45908:10;45920:7;45929:6;45897:10;:39::i;:::-;45889:48;;;;;;;;46266:11;;;:49;;-1:-1:-1;46290:10:0;46281:20;;;;:8;:20;;;;;;;;-1:-1:-1;;;;;46281:29:0;;;;;;;;;;:34;46266:49;46265:99;;;;;46320:39;46339:10;46351:7;46320:18;:39::i;:::-;:44;46265:99;46257:108;;;;;;;;46387:10;46378:20;;;;:8;:20;;;;;;;;-1:-1:-1;;;;;46378:29:0;;;;;;;;;;;;:38;;;46432:37;;;;;;;46378:29;;46387:10;46432:37;;;;;;;;;;;-1:-1:-1;46487:4:0;45706:793;;;;:::o;132057:345::-;132211:16;;132256:8;;132211:66;;;;;;132244:10;132211:66;;;;-1:-1:-1;;;;;132256:8:0;;;132211:66;;;;;;;;;;;;;:16;;;;;:32;;:66;;;;;;;;;;;;;;:16;;:66;;;5:2:-1;;;;30:1;27;20:12;5:2;132211:66:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;132211:66:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;132211:66:0;132203:75;;;;;;;;132289:8;:21;;-1:-1:-1;;;;;132289:21:0;;;-1:-1:-1;;132289:21:0;;;;;;;;;132365:16;;132326:68;;;132343:8;;;132326:68;;;;;;;;;132365:16;132326:68;;;;132383:10;132326:68;;;;;;;;;;;;;;132057:345;:::o;131548:156::-;131643:2;14570:33;14594:8;14570:23;:33::i;:::-;131663;131673:10;131685:2;131689:6;131663:9;:33::i;:::-;131548:156;;;:::o;59453:158::-;59528:7;59560:43;59582:20;:18;:20::i;:::-;59560:21;:43::i;:::-;59553:50;;59453:158;:::o;132771:87::-;132842:8;;-1:-1:-1;;;;;132842:8:0;132771:87;:::o;46881:596::-;46979:12;47009:15;47027:36;47046:4;47052:10;47027:18;:36::i;:::-;47009:54;-1:-1:-1;47078:12:0;;47074:299;;;-1:-1:-1;;;;;;47180:14:0;;;;;;:8;:14;;;;;;;;47195:10;47180:26;;;;;;;;;47325:36;;;;;;47074:299;47391:17;;;;47383:26;;;;;;47420:27;47430:4;47436:2;47440:6;47420:9;:27::i;:::-;-1:-1:-1;47465:4:0;;46881:596;-1:-1:-1;;;;46881:596:0:o;36715:118::-;36817:8;;;;36715:118;:::o;60601:186::-;60709:7;60741:38;60761:5;60768:10;60741:19;:38::i;:::-;60734:45;60601:186;-1:-1:-1;;;60601:186:0:o;36841:117::-;36943:7;36936:14;;;;;;;;-1:-1:-1;;36936:14:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36912:6;;36936:14;;36943:7;;36936:14;;36943:7;36936:14;;;;;;;;;;;;;;;;;;;;;;;;4174:656;3733:13;;:54;;;;;;3755:10;3733:54;;;;2546:66;3733:54;;;;;;3773:4;3733:54;;;;-1:-1:-1;3779:7:0;;-1:-1:-1;;3779:7:0;3733:54;;;;;;-1:-1:-1;;2546:66:0;;-1:-1:-1;;;;;3733:13:0;;;;:21;;:54;;;;;;;;;;;;;;-1:-1:-1;3733:13:0;:54;;;5:2:-1;;;;30:1;27;20:12;5:2;3733:54:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;3733:54:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;3733:54:0;3725:63;;;;;;;;4488:77;;;;;;-1:-1:-1;;;;;4488:77:0;;;;;;;2546:66;4488:77;;;;4551:4;4488:77;;;;-1:-1:-1;4557:7:0;;-1:-1:-1;;4557:7:0;4488:77;;;;;;:17;;;;;;:77;;;;;;;;;;;;;;;;;;:17;:77;;;5:2:-1;;;;30:1;27;20:12;5:2;4488:77:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;4488:77:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;4488:77:0;4480:86;;;;;;;;4677:13;;;-1:-1:-1;;;;;4701:25:0;;;-1:-1:-1;;4701:25:0;;;;;;;4766:56;;;4789:10;4766:56;;4677:13;;;;4766:56;;;;;;;;;;;;;;;4677:13;;-1:-1:-1;4766:56:0;;;;;;;;;;4174:656;;;;:::o;131777:272::-;129931:16;;:59;;;;;;131862:10;129931:59;;;;;;;;;;;;;;;;;;;;131862:10;;131874:6;;-1:-1:-1;;;;;129931:16:0;;;;:32;;:59;;;;;;;;;;;;;;:16;;:59;;;5:2:-1;;;;30:1;27;20:12;5:2;129931:59:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;129931:59:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;129931:59:0;129923:93;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;131907:10;14570:33;14594:8;14570:23;:33::i;:::-;131935:34;131950:10;131962:6;131935:14;:34::i;:::-;132016:16;;131985:56;;;-1:-1:-1;;;;;132016:16:0;;;131985:56;;;;;;;;;;132004:10;;131985:56;;;;;;;;;130027:1;131777:272;;;:::o;16984:174::-;-1:-1:-1;;;;;17127:23:0;17087:15;17127:23;;;:12;:23;;;;;;;16984:174::o;59748:182::-;59834:15;59874:48;59894:5;59901:20;:18;:20::i;:::-;59874:19;:48::i;17166:137::-;17277:11;:18;17166:137;:::o;61000:144::-;61074:25;61124:12;-1:-1:-1;;;;;61124:12:0;61000:144;:::o;61563:719::-;-1:-1:-1;;;;;62018:16:0;;61992:23;62018:16;;;:9;:16;;;;;;;;62093:13;;62076:31;;;;;;;;;;;;;;;;61655:12;;62018:16;;61655:12;;62076:31;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;62045:62;;62135:1;62122:14;;62118:129;62143:13;;62138:18;;62118:129;;;62179:56;;;;;;;;;62195:6;62202:2;62195:10;;;;;;;;;;;;;;;;;;;;:21;;;62179:56;;;;62218:6;62225:2;62218:10;;;;;;;;;;;;;;;;;;;;:16;;;62179:56;;;:8;62188:2;62179:12;;;;;;;;;;;;;;;;;;:56;62158:4;;62118:129;;;-1:-1:-1;62266:8:0;61563:719;-1:-1:-1;;;61563:719:0:o;134181:169::-;134272:66;134340:1;134181:169;;:::o;16423:553::-;16545:35;16595:28;16638:19;16672:13;16713:33;16749:11;16761:14;16749:27;;;;;;;;;;;;;;;;;;;;16713:63;;16809:9;:37;;;;;;;;;;-1:-1:-1;;;;;16809:37:0;16861:9;:30;;;16906:9;:22;;16943:14;16787:181;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16423:553;;;;;;:::o;36592:115::-;36693:6;36686:13;;;;;;;;-1:-1:-1;;36686:13:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36662:6;;36686:13;;36693:6;;36686:13;;36693:6;36686:13;;;;;;;;;;;;;;;;;;;;;;;;60795:141;60876:7;60908:20;:18;:20::i;60426:167::-;60520:7;60552:33;60574:10;60552:21;:33::i;131207:269::-;129739:16;;:57;;;;;;129773:10;129739:57;;;;131296:4;129739:57;;;;;;;;;;;;;;131296:4;;131303:6;;-1:-1:-1;;;;;129739:16:0;;;;:33;;:57;;;;;;;;;;;;;;:16;;:57;;;5:2:-1;;;;30:1;27;20:12;5:2;129739:57:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;129739:57:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;129739:57:0;129731:92;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;131336:10;14570:33;14594:8;14570:23;:33::i;:::-;131364:35;131380:10;131392:6;131364:15;:35::i;:::-;131443:16;;131415:53;;;-1:-1:-1;;;;;131443:16:0;;;131415:53;;;;;;;;;;131431:10;;131415:53;;;;;;;;;129834:1;131207:269;;;:::o;61225:148::-;61347:18;;61225:148;:::o;60192:173::-;60272:12;60302:33;60312:10;60324:2;60328:6;60302:9;:33::i;:::-;-1:-1:-1;60353:4:0;60192:173;;;;:::o;132520:118::-;132574:7;132601:29;132616:13;:11;:13::i;:::-;132601:14;:29::i;132646:117::-;132731:24;;132646:117;:::o;133698:426::-;133790:4;133881:52;133910:10;133922:2;133926:6;133881:28;:52::i;:::-;133993:14;134004:2;133993:10;:14::i;:::-;133989:106;;;134040:2;-1:-1:-1;;;;;134024:33:0;;134058:10;134070:6;134078:4;134024:59;;;;;-1:-1:-1;;;134024:59:0;;;;;;;-1:-1:-1;;;;;134024:59:0;-1:-1:-1;;;;;134024:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;134024:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;134024:59:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;134024:59:0;;;;133989:106;-1:-1:-1;134112:4:0;133698:426;;;;;:::o;15811:604::-;15914:35;15964:28;16007:19;16041:13;16124:12;16172:33;16111:1;16090:11;:18;;;;:22;16082:31;;;;;;;;16139:11;:18;;-1:-1:-1;;16139:22:0;;;-1:-1:-1;16139:22:0;;16208:17;;;;;;;;;;;;;;;;16172:53;;16258:9;:37;;;;;;;;;;-1:-1:-1;;;;;16258:37:0;16310:9;:30;;;16355:9;:22;;16392:4;16236:171;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15811:604;;;;;;:::o;48051:427::-;48193:12;48231:24;48239:7;48248:6;48231:7;:24::i;:::-;48223:33;;;;;;;;48279:140;;;;;48334:10;48279:140;;;;;;;;;;;;48380:4;48279:140;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;48279:40:0;;;;;48334:10;48359:6;;48380:4;48399:9;;48279:140;;;;;;;;;;;;;;;;-1:-1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;48279:140:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;48279:140:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;48279:140:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;48279:140:0;;-1:-1:-1;48430:16:0;;;;;;;;132410:102;132488:16;;132410:102;:::o;133058:425::-;133223:16;;:67;;;;;;133264:10;133223:67;;;;-1:-1:-1;;;;;133223:67:0;;;;;;;;;:16;;;;;:40;;:67;;;;;;;;;;;;;;:16;;:67;;;5:2:-1;;;;30:1;27;20:12;5:2;133223:67:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;133223:67:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;133223:67:0;133215:108;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;133334:16;:56;;-1:-1:-1;;;;;133334:56:0;;;-1:-1:-1;;133334:56:0;;;;;;;;;133406:69;;;133431:16;;;;133406:69;;;;;;;;;133464:10;133406:69;;;;;;;;;;;;;;133058:425;:::o;44938:311::-;45041:17;45076:16;45095:34;45114:5;45121:7;45095:18;:34::i;:::-;45076:53;;45155:1;45144:8;:12;45140:60;;;45180:8;45173:15;;;;45140:60;-1:-1:-1;;;;;45217:15:0;;;;;;;:8;:15;;;;;;;;:24;;;;;;;;;;;-1:-1:-1;44938:311:0;;;;;;:::o;15646:157::-;15774:21;;-1:-1:-1;;;;;15774:21:0;15646:157;:::o;15199:439::-;15321:32;;:::i;:::-;15293:10;14712:30;14722:19;14712:9;:30::i;:::-;14704:39;;;;;;;;15356:175;;;;;;;;15416:10;15356:175;;15463:15;15356:175;;;;;;;;;;;;;15542:11;27:10:-1;;39:1;23:18;;45:23;;;-1:-1;15542:27:0;;;;;;;;;;;;;;;;-1:-1:-1;;15542:27:0;-1:-1:-1;;;;;15542:27:0;;;;;;;;;;;;;;;;;;;15356:175;;-1:-1:-1;23:18;;15356:175:0;;15542:27;;;;;;;;;;:::i;:::-;;;;;15585:45;15605:10;15617:12;15585:45;;;;-1:-1:-1;;;;;15585:45:0;-1:-1:-1;;;;;15585:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;15585:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15199:439;;;:::o;133491:103::-;133570:16;;-1:-1:-1;;;;;133570:16:0;133491:103;:::o;132866:126::-;132956:28;;-1:-1:-1;;;;;132956:28:0;132866:126;:::o;4838:135::-;4952:13;;-1:-1:-1;;;;;4952:13:0;4838:135;:::o;34444:251::-;34530:7;34680:6;34659:18;;;:27;34649:6;:38;34642:45;;34444:251;;;:::o;134821:263::-;134991:10;134966:5;14570:33;14594:8;14570:23;:33::i;:::-;135026:16;;:50;;;;;;-1:-1:-1;;;;;135026:50:0;;;;;;;;;;;;;;;;;;;;;;:16;;;;;:26;;:50;;;;;;;;;;;;;;:16;;:50;;;5:2:-1;;;;30:1;27;20:12;5:2;135026:50:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;135026:50:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;135026:50:0;;134821:263;-1:-1:-1;;;;;134821:263:0:o;135092:223::-;135263:16;;:44;;;;;;-1:-1:-1;;;;;135263:44:0;;;;;;;;;;;;;;;;135231:7;;135263:16;;;;;:28;;:44;;;;;;;;;;;;;;;135231:7;135263:16;:44;;;5:2:-1;;;;30:1;27;20:12;5:2;135263:44:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;135263:44:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;135263:44:0;;135092:223;-1:-1:-1;;;135092:223:0:o;17452:284::-;-1:-1:-1;;;;;17540:22:0;;;;;;:12;:22;;;;;;:27;17537:192;;;17592:11;:18;17613:1;-1:-1:-1;17584:31:0;;;;;;-1:-1:-1;;;;;17630:22:0;;;;;;:12;:22;;;;;;17655:12;17630:37;;17687:30;;;17630:22;17687:30;17537:192;17452:284;:::o;64376:1417::-;64999:27;;;;-1:-1:-1;;;;;64549:16:0;;;;64541:25;;;;;;64703:1;64678:13;:11;:13::i;:::-;-1:-1:-1;;;;;64678:27:0;;:85;;;;64730:13;:11;:13::i;:::-;-1:-1:-1;;;;;64730:31:0;;:33;;;;;-1:-1:-1;;;64730:33:0;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;64730:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;64730:33:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;64730:33:0;64709:18;:16;:18::i;:::-;:54;64678:85;64670:94;;;;;;;;64839:29;64851:4;64857:2;64861:6;64839:11;:29::i;:::-;64831:38;;;;;;;;65029:15;65039:4;65029:9;:15::i;:::-;64999:45;-1:-1:-1;65063:29:0;;;;65055:38;;;;;;-1:-1:-1;;;;;65289:15:0;;;;;;:9;:15;;;;;65241:28;;;;-1:-1:-1;65280:41:0;;65241:28;65280:8;:41::i;:::-;65473:13;65483:2;65473:9;:13::i;:::-;65445:41;-1:-1:-1;;65520:26:0;;;65564:33;;;;65557:41;;;;-1:-1:-1;;;;;65640:13:0;;;;;;:9;:13;;;;;65631:37;;65655:12;65631:8;:37::i;:::-;65774:2;-1:-1:-1;;;;;65759:26:0;65768:4;-1:-1:-1;;;;;65759:26:0;;65778:6;65759:26;;;;;;;;;;;;;;;;;;64376:1417;;;;;;;:::o;34209:227::-;34293:7;34395:33;34411:15;34395:7;:33::i;62379:720::-;62483:7;62534:18;62483:7;62647:30;62534:18;62666:10;62647;:30::i;:::-;62643:103;;;62701:33;62712:6;62720:10;62732:1;62701:10;:33::i;:::-;62694:40;;;;62643:103;62824:12;;-1:-1:-1;;;;;62824:12:0;62816:26;62812:219;;62908:10;62887:18;;:31;:65;;62934:18;;62887:65;;;62921:10;62887:65;62859:93;;62974:12;;;;;;;;;-1:-1:-1;;;;;62974:12:0;-1:-1:-1;;;;;62974:26:0;;63001:17;62974:45;;;;;-1:-1:-1;;;62974:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;62974:45:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;62974:45:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;62974:45:0;;-1:-1:-1;62967:52:0;;62812:219;63090:1;63083:8;;62379:720;;;;;;:::o;63176:737::-;-1:-1:-1;;;;;63345:16:0;;63294:7;63345:16;;;:9;:16;;;;;63294:7;63456:30;63345:16;63475:10;63456;:30::i;:::-;63452:103;;;63510:33;63521:6;63529:10;63541:1;63510:10;:33::i;:::-;63503:40;;;;63452:103;63649:1;63625:12;-1:-1:-1;;;;;63625:12:0;:26;63621:224;;63717:10;63696:18;;:31;:65;;63743:18;;63696:65;;;63730:10;63696:65;63783:12;;;:50;;;;;;-1:-1:-1;;;;;63783:50:0;;;;;;;;;;;;;;;63668:93;;-1:-1:-1;63783:12:0;;;:24;;:50;;;;;;;;;;;;;;;;;;:12;:50;;;5:2:-1;;;;30:1;27;20:12;5:2;63783:50:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;63783:50:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;63783:50:0;;-1:-1:-1;63776:57:0;;63621:224;63904:1;63897:8;;63176:737;;;;;;;:::o;68674:762::-;68961:22;;;;;68862:13;:11;:13::i;:::-;-1:-1:-1;;;;;68862:27:0;;:85;;;;68914:13;:11;:13::i;:::-;-1:-1:-1;;;;;68914:31:0;;:33;;;;;-1:-1:-1;;;68914:33:0;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;68914:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;68914:33:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;68914:33:0;68893:18;:16;:18::i;:::-;:54;68862:85;68854:94;;;;;;;;68986:13;:11;:13::i;:::-;68961:38;-1:-1:-1;69018:24:0;;;;69010:33;;;;;;69086:16;69096:5;69086:9;:16::i;:::-;69056:46;-1:-1:-1;69121:29:0;;;;69113:38;;;;;;-1:-1:-1;;69189:23:0;;;69248:28;;;69287:44;69296:18;69189:23;69287:8;:44::i;:::-;-1:-1:-1;;;;;69351:16:0;;;;;;:9;:16;;;;;69342:42;;69369:14;69342:8;:42::i;:::-;69402:26;;;;;;;;69418:1;;-1:-1:-1;;;;;69402:26:0;;;;;;;;;;;;68674:762;;;;;;:::o;67612:888::-;67978:22;;;;-1:-1:-1;;;;;67749:19:0;;;;67741:28;;;;;;67904:1;67879:13;:11;:13::i;:::-;-1:-1:-1;;;;;67879:27:0;;:85;;;;67931:13;:11;:13::i;:::-;-1:-1:-1;;;;;67931:31:0;;:33;;;;;-1:-1:-1;;;67931:33:0;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;67931:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;67931:33:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;67931:33:0;67910:18;:16;:18::i;:::-;:54;67879:85;67871:94;;;;;;;;68003:13;:11;:13::i;:::-;67978:38;-1:-1:-1;68052:23:0;;;;-1:-1:-1;68094:32:0;;;;68086:41;;;;;;68190:16;68200:5;68190:9;:16::i;:::-;68162:44;-1:-1:-1;;68240:26:0;;;68284:33;;;;68277:41;;;;68353:44;68362:18;68382:14;68353:8;:44::i;:::-;-1:-1:-1;;;;;68417:16:0;;;;;;:9;:16;;;;;68408:40;;68435:12;68408:8;:40::i;:::-;68466:26;;;;;;;;-1:-1:-1;;;;;68466:26:0;;;68475:1;;68466:26;;;;;;;;;67612:888;;;;;;:::o;135529:159::-;135623:7;135664:16;;135655:6;:25;;;;;;;;;135529:159;-1:-1:-1;;135529:159:0:o;25338:230::-;25426:4;25516:17;;25552:8;;25338:230::o;135369:152::-;135505:8;;-1:-1:-1;;;;;135505:8:0;;;135482:31;;;;135369:152::o;134501:312::-;134665:10;134641:4;14570:33;14594:8;14570:23;:33::i;:::-;134748:16;;:57;;;;;;134776:10;134748:57;;;;-1:-1:-1;;;;;134748:57:0;;;;;;;;;;;;;;;;;;;;;;:16;;;;;:27;;:57;;;;;;;;;;;;;;:16;;:57;;;5:2:-1;;;;30:1;27;20:12;52564:1655:0;52742:25;52870:10;53177:12;53220:19;53390:15;53804:23;52770:20;:18;:20::i;:::-;52883:13;;52742:48;;-1:-1:-1;52883:18:0;;-1:-1:-1;52912:253:0;;;;53003:114;;;;;;;;;;;;;;;;;;;27:10:-1;;39:1;23:18;;;45:23;;-1:-1;52973:159:0;;;;;;;;;;;;;;;;;;;;;;;53147:7;;52912:253;53192:13;;-1:-1:-1;;53192:17:0;;;-1:-1:-1;53268:17:0;;53192:6;;:17;;53242:12;;;;;;;;;;;;;;;;:23;;;:43;53220:65;;53300:14;53296:916;;;53430:5;53408:6;53415:4;53408:12;;;;;;;;;;;;;;;;;;;;:18;;;:27;53390:45;;53454:10;53450:57;;;53485:7;;53450:57;53586:114;;;;;;;;;;;;;;;;;;;27:10:-1;;39:1;23:18;;;45:23;;-1:-1;53556:159:0;;;;;;;;;;;;;;;;;;;;;;;53296:916;;;53837:1;53830:4;:8;:43;;;;;53868:5;53842:6;53856:1;53849:4;:8;53842:16;;;;;;;;;;;;;;;;;;;;:22;;;:31;53830:43;53804:69;;53892:18;53888:224;;;54025:6;54032:4;54025:12;;;;;;;;;;;;;;;;;;;;;;54018:19;;;;;;54056:15;;;:6;-1:-1:-1;;54056:15:0;;;:::i;:::-;;54090:7;;53888:224;54195:5;54174:6;54181:4;54174:12;;;;;;;;;;;;;;;;;;;;:18;;:26;;;;53296:916;52564:1655;;;;;;;;:::o;50250:290::-;50394:4;50438:20;:18;:20::i;:::-;50424:34;;;50416:43;;;;;;50477:13;;50493:1;-1:-1:-1;50477:55:0;;;;;50522:10;50498:6;50505:1;50498:9;;;;;;;;;;;;;;;;;;;;:20;;;:34;;50470:62;;50250:290;;;;:::o;51181:1206::-;51356:7;51596:12;51639:20;51790:21;51985:11;52011;52073;51403:20;:18;:20::i;:::-;51389:34;;;51381:43;;;;;;51465:13;;:18;51461:70;;;51507:12;51500:19;;;;51461:70;51611:13;;-1:-1:-1;;51611:17:0;;;-1:-1:-1;51611:6:0;;:17;;51662:12;;;;;;;;;;;;;;;;;;;:23;;-1:-1:-1;51700:26:0;;;51696:84;;51750:6;51757:4;51750:12;;;;;;;;;;;;;;;;;;;;:18;;;51743:25;;;;51696:84;51814:6;51821:1;51814:9;;;;;;;;;;;;;;;;;;;;:20;;;51790:44;;51862:13;51849:10;:26;51845:78;;;51899:12;51892:19;;;;51845:78;51999:1;51985:15;;52025:4;52011:18;;52040:305;52053:3;52047;:9;52040:305;;;52105:1;52100;52088:9;;;:13;52087:19;52073:33;;52224:10;52198:6;52205:3;52198:11;;;;;;;;;;;;;;;;;;;;;;;:22;:36;52194:140;;52261:3;52255:9;;52194:140;;;52317:1;52311:3;:7;52305:13;;52194:140;52040:305;;;52362:6;52369:3;52362:11;;;;;;;;;;;;;;;;;;;;:17;;;52355:24;;51181:1206;;;;;;;;;;;;:::o;128203:7488::-;;;;;;;;;;;;;;;105:10:-1;128203:7488:0;88:34:-1;-1:-1;128203:7488:0;;;-1:-1:-1;;128203:7488:0:o;:::-;;;;;;;;;;-1:-1:-1;128203:7488:0;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;128203:7488:0;;;-1:-1:-1;128203:7488:0;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Swarm Source

bzzr://5e4fe0c7a1712aa620306235bb48f56ebc5ca7e487a50a84fcace70d907d3330
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.