ETH Price: $3,624.15 (+0.07%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

TokenTracker

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Set Total On Oth...215484422025-01-04 3:31:1115 hrs ago1735961471IN
0x1f426C51...F1c381bfF
0 ETH0.000213555.2816715
Set Total On Oth...215412772025-01-03 3:30:2339 hrs ago1735875023IN
0x1f426C51...F1c381bfF
0 ETH0.000275936.82460543
Set Total On Oth...215341062025-01-02 3:30:232 days ago1735788623IN
0x1f426C51...F1c381bfF
0 ETH0.0021421752.9808324
Set Total On Oth...215269402025-01-01 3:30:233 days ago1735702223IN
0x1f426C51...F1c381bfF
0 ETH0.000104972.59627891
Set Total On Oth...215197802024-12-31 3:30:234 days ago1735615823IN
0x1f426C51...F1c381bfF
0 ETH0.000144723.57939535
Set Total On Oth...215126182024-12-30 3:30:235 days ago1735529423IN
0x1f426C51...F1c381bfF
0 ETH0.000160923.98003896
Set Total On Oth...215054512024-12-29 3:30:236 days ago1735443023IN
0x1f426C51...F1c381bfF
0 ETH0.000119712.96077011
Set Total On Oth...214982862024-12-28 3:30:357 days ago1735356635IN
0x1f426C51...F1c381bfF
0 ETH0.00012092.99037468
Set Total On Oth...214911242024-12-27 3:30:238 days ago1735270223IN
0x1f426C51...F1c381bfF
0 ETH0.000164814.07628793
Set Total On Oth...214839652024-12-26 3:30:239 days ago1735183823IN
0x1f426C51...F1c381bfF
0 ETH0.000211125.22171045
Set Total On Oth...214768132024-12-25 3:30:4710 days ago1735097447IN
0x1f426C51...F1c381bfF
0 ETH0.000150453.7212064
Set Total On Oth...214696612024-12-24 3:30:3511 days ago1735011035IN
0x1f426C51...F1c381bfF
0 ETH0.000239245.91699648
Set Total On Oth...214625132024-12-23 3:30:2312 days ago1734924623IN
0x1f426C51...F1c381bfF
0 ETH0.0004200510.38879218
Set Total On Oth...214553622024-12-22 3:30:2313 days ago1734838223IN
0x1f426C51...F1c381bfF
0 ETH0.000217345.37537559
Set Total On Oth...214482132024-12-21 3:30:2314 days ago1734751823IN
0x1f426C51...F1c381bfF
0 ETH0.0004233910.47152004
Set Total On Oth...214410562024-12-20 3:30:2315 days ago1734665423IN
0x1f426C51...F1c381bfF
0 ETH0.000376819.31948499
Set Total On Oth...214338922024-12-19 3:30:2316 days ago1734579023IN
0x1f426C51...F1c381bfF
0 ETH0.0005466413.51977158
Set Total On Oth...214267432024-12-18 3:30:3517 days ago1734492635IN
0x1f426C51...F1c381bfF
0 ETH0.0004129910.21442319
Set Total On Oth...214195752024-12-17 3:30:2318 days ago1734406223IN
0x1f426C51...F1c381bfF
0 ETH0.000397459.82986386
Set Total On Oth...214124032024-12-16 3:30:2319 days ago1734319823IN
0x1f426C51...F1c381bfF
0 ETH0.0004845111.98304461
Set Total On Oth...214052462024-12-15 3:30:2320 days ago1734233423IN
0x1f426C51...F1c381bfF
0 ETH0.000349798.65130324
Set Total On Oth...213980782024-12-14 3:30:2321 days ago1734147023IN
0x1f426C51...F1c381bfF
0 ETH0.0004215610.42618498
Set Total On Oth...213909232024-12-13 3:32:2322 days ago1734060743IN
0x1f426C51...F1c381bfF
0 ETH0.0004704411.6352753
Set Total On Oth...213837482024-12-12 3:30:2323 days ago1733974223IN
0x1f426C51...F1c381bfF
0 ETH0.0007651718.92450372
Set Total On Oth...213765952024-12-11 3:30:2324 days ago1733887823IN
0x1f426C51...F1c381bfF
0 ETH0.0005999614.83838009
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
MorpherState

Compiler Version
v0.5.16+commit.9c3226ce

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, GNU GPLv3 license

Contract Source Code (Solidity Multiple files format)

File 1 of 15: MorpherState.sol
pragma solidity 0.5.16;

import "./Ownable.sol";
import "./SafeMath.sol";
import "./IMorpherToken.sol";

// ----------------------------------------------------------------------------------
// Data and token balance storage of the Morpher platform
// Writing access is only granted to platform contracts. The contract can be paused
// by an elected platform administrator (see MorpherGovernance) to perform protocol updates.
// ----------------------------------------------------------------------------------

contract MorpherState is Ownable {
    using SafeMath for uint256;

    bool public mainChain;
    uint256 public totalSupply;
    uint256 public totalToken;
    uint256 public totalInPositions;
    uint256 public totalOnOtherChain;
    uint256 public maximumLeverage = 10**9; // Leverage precision is 1e8, maximum leverage set to 10 initially
    uint256 constant PRECISION = 10**8;
    uint256 constant DECIMALS = 18;
    uint256 constant REWARDPERIOD = 1 days;
    bool public paused = false;

    address public morpherGovernance;
    address public morpherRewards;
    address public administrator;
    address public oracleContract;
    address public sideChainOperator;
    address public morpherBridge;
    address public morpherToken;

    uint256 public rewardBasisPoints;
    uint256 public lastRewardTime;

    bytes32 public sideChainMerkleRoot;
    uint256 public sideChainMerkleRootWrittenAtTime;

    // Set initial withdraw limit from sidechain to 20m token or 2% of initial supply
    uint256 public mainChainWithdrawLimit24 = 2 * 10**25;

    mapping(address => bool) private stateAccess;
    mapping(address => bool) private transferAllowed;

    mapping(address => uint256) private balances;
    mapping(address => mapping(address => uint256)) private allowed;

    mapping(bytes32 => bool) private marketActive;

    // ----------------------------------------------------------------------------
    // Position struct records virtual futures
    // ----------------------------------------------------------------------------
    struct position {
        uint256 lastUpdated;
        uint256 longShares;
        uint256 shortShares;
        uint256 meanEntryPrice;
        uint256 meanEntrySpread;
        uint256 meanEntryLeverage;
        uint256 liquidationPrice;
        bytes32 positionHash;
    }

    // ----------------------------------------------------------------------------
    // A portfolio is an address specific collection of postions
    // ----------------------------------------------------------------------------
    mapping(address => mapping(bytes32 => position)) private portfolio;

    // ----------------------------------------------------------------------------
    // Record all addresses that hold a position of a market, needed for clean stock splits
    // ----------------------------------------------------------------------------
    struct hasExposure {
        uint256 maxMappingIndex;
        mapping(address => uint256) index;
        mapping(uint256 => address) addy;
    }

    mapping(bytes32 => hasExposure) private exposureByMarket;

    // ----------------------------------------------------------------------------
    // Bridge Variables
    // ----------------------------------------------------------------------------
    mapping (address => uint256) private tokenClaimedOnThisChain;
    mapping (address => uint256) private tokenSentToLinkedChain;
    mapping (address => uint256) private tokenSentToLinkedChainTime;
    mapping (bytes32 => bool) private positionClaimedOnMainChain;

    uint256 public lastWithdrawLimitReductionTime;
    uint256 public last24HoursAmountWithdrawn;
    uint256 public withdrawLimit24Hours;
    uint256 public inactivityPeriod = 3 days;
    uint256 public transferNonce;
    bool public fastTransfersEnabled;

    // ----------------------------------------------------------------------------
    // Sidechain spam protection
    // ----------------------------------------------------------------------------

    mapping(address => uint256) private lastRequestBlock;
    mapping(address => uint256) private numberOfRequests;
    uint256 public numberOfRequestsLimit;

    // ----------------------------------------------------------------------------
    // Events
    // ----------------------------------------------------------------------------
    event StateAccessGranted(address indexed whiteList, uint256 indexed blockNumber);
    event StateAccessDenied(address indexed blackList, uint256 indexed blockNumber);

    event TransfersEnabled(address indexed whiteList);
    event TransfersDisabled(address indexed blackList);

    event Transfer(address indexed sender, address indexed recipient, uint256 amount);
    event Mint(address indexed recipient, uint256 amount, uint256 totalToken);
    event Burn(address indexed recipient, uint256 amount, uint256 totalToken);
    event NewTotalSupply(uint256 newTotalSupply);
    event NewTotalOnOtherChain(uint256 newTotalOnOtherChain);
    event NewTotalInPositions(uint256 newTotalOnOtherChain);
    event OperatingRewardMinted(address indexed recipient, uint256 amount);

    event RewardsChange(address indexed rewardsAddress, uint256 indexed rewardsBasisPoints);
    event LastRewardTime(uint256 indexed rewardsTime);
    event GovernanceChange(address indexed governanceAddress);
    event TokenChange(address indexed tokenAddress);
    event AdministratorChange(address indexed administratorAddress);
    event OracleChange(address indexed oracleContract);
    event MaximumLeverageChange(uint256 maxLeverage);
    event MarketActivated(bytes32 indexed activateMarket);
    event MarketDeActivated(bytes32 indexed deActivateMarket);
    event BridgeChange(address _bridgeAddress);
    event SideChainMerkleRootUpdate(bytes32 indexed sideChainMerkleRoot);
    event NewSideChainOperator(address indexed sideChainOperator);
    event NumberOfRequestsLimitUpdate(uint256 _numberOfRequests);

    event MainChainWithdrawLimitUpdate(uint256 indexed mainChainWithdrawLimit24);
    event TokenSentToLinkedChain(address _address, uint256 _token, uint256 _totalTokenSent, bytes32 indexed _tokenSentToLinkedChainHash);
    event TransferredTokenClaimed(address _address, uint256 _token);
    event LastWithdrawAt();
    event RollingWithdrawnAmountUpdated(uint256 _last24HoursAmountWithdrawn, uint256 _lastWithdrawLimitReductionTime);
    event WithdrawLimitUpdated(uint256 _amount);
    event InactivityPeriodUpdated(uint256 _periodLength);
    event FastWithdrawsDisabled();
    event NewBridgeNonce(uint256 _transferNonce);
    event Last24HoursAmountWithdrawnReset();

    event StatePaused(address administrator, bool _paused);

    event SetAllowance(address indexed sender, address indexed spender, uint256 tokens);
    event SetPosition(bytes32 indexed positionHash,
        address indexed sender,
        bytes32 indexed marketId,
        uint256 timeStamp,
        uint256 longShares,
        uint256 shortShares,
        uint256 meanEntryPrice,
        uint256 meanEntrySpread,
        uint256 meanEntryLeverage,
        uint256 liquidationPrice
    );
    event SetBalance(address indexed account, uint256 balance, bytes32 indexed balanceHash);
    event TokenTransferredToOtherChain(address indexed account, uint256 tokenTransferredToOtherChain, bytes32 indexed transferHash);

    modifier notPaused {
        require(paused == false, "MorpherState: Contract paused, aborting");
        _;
    }

    modifier onlyPlatform {
        require(stateAccess[msg.sender] == true, "MorpherState: Only Platform is allowed to execute operation.");
        _;
    }

    modifier onlyGovernance {
        require(msg.sender == getGovernance(), "MorpherState: Calling contract not the Governance Contract. Aborting.");
        _;
    }

    modifier onlyAdministrator {
        require(msg.sender == getAdministrator(), "MorpherState: Caller is not the Administrator. Aborting.");
        _;
    }

    modifier onlySideChainOperator {
        require(msg.sender == sideChainOperator, "MorpherState: Caller is not the Sidechain Operator. Aborting.");
        _;
    }

    modifier canTransfer {
        require(getCanTransfer(msg.sender), "MorpherState: Caller may not transfer token. Aborting.");
        _;
    }

    modifier onlyBridge {
        require(msg.sender == getMorpherBridge(), "MorpherState: Caller is not the Bridge. Aborting.");
        _;
    }

    modifier onlyMainChain {
        require(mainChain == true, "MorpherState: Can only be called on mainchain.");
        _;
    }

    modifier onlySideChain {
        require(mainChain == false, "MorpherState: Can only be called on mainchain.");
        _;
    }

    constructor(bool _mainChain, address _sideChainOperator, address _morpherTreasury) public {
        // @Deployer: Transfer State Ownership to cold storage address after deploying protocol
        mainChain = _mainChain; // true for Ethereum, false for Morpher PoA sidechain
        setLastRewardTime(now);
        uint256 _sideChainMint = 575000000 * 10**(DECIMALS);
        uint256 _mainChainMint = 425000000 * 10**(DECIMALS);
        grantAccess(owner());
        setSideChainOperator(owner());
        if (mainChain == false) { // Create token only on sidechain
            balances[owner()] = _sideChainMint; // Create airdrop and team token on sidechain
            totalToken = _sideChainMint;
            emit Mint(owner(), balanceOf(owner()), _sideChainMint);
            setRewardBasisPoints(0); // Reward is minted on mainchain
            setRewardAddress(address(0));
            setTotalOnOtherChain(_mainChainMint);
        } else {
            balances[owner()] = _mainChainMint; // Create treasury and investor token on mainchain
            totalToken = _mainChainMint;
            emit Mint(owner(), balanceOf(owner()), _mainChainMint);
            setRewardBasisPoints(15000); // 15000 / PRECISION = 0.00015
            setRewardAddress(_morpherTreasury);
            setTotalOnOtherChain(_sideChainMint);
        }
        fastTransfersEnabled = true;
        setNumberOfRequestsLimit(3);
        setMainChainWithdrawLimit(totalSupply / 50);
        setSideChainOperator(_sideChainOperator);
        denyAccess(owner());
    }

    // ----------------------------------------------------------------------------
    // Setter/Getter functions for market wise exposure
    // ----------------------------------------------------------------------------

    function getMaxMappingIndex(bytes32 _marketId) public view returns(uint256 _maxMappingIndex) {
        return exposureByMarket[_marketId].maxMappingIndex;
    }

    function getExposureMappingIndex(bytes32 _marketId, address _address) public view returns(uint256 _mappingIndex) {
        return exposureByMarket[_marketId].index[_address];
    }

    function getExposureMappingAddress(bytes32 _marketId, uint256 _mappingIndex) public view returns(address _address) {
        return exposureByMarket[_marketId].addy[_mappingIndex];
    }

    function setMaxMappingIndex(bytes32 _marketId, uint256 _maxMappingIndex) public onlyPlatform {
        exposureByMarket[_marketId].maxMappingIndex = _maxMappingIndex;
    }

    function setExposureMapping(bytes32 _marketId, address _address, uint256 _index) public onlyPlatform  {
        setExposureMappingIndex(_marketId, _address, _index);
        setExposureMappingAddress(_marketId, _address, _index);
    }

    function setExposureMappingIndex(bytes32 _marketId, address _address, uint256 _index) public onlyPlatform {
        exposureByMarket[_marketId].index[_address] = _index;
    }

    function setExposureMappingAddress(bytes32 _marketId, address _address, uint256 _index) public onlyPlatform {
        exposureByMarket[_marketId].addy[_index] = _address;
    }

    // ----------------------------------------------------------------------------
    // Setter/Getter functions for bridge variables
    // ----------------------------------------------------------------------------
    function setTokenClaimedOnThisChain(address _address, uint256 _token) public onlyBridge {
        tokenClaimedOnThisChain[_address] = _token;
        emit TransferredTokenClaimed(_address, _token);
    }

    function getTokenClaimedOnThisChain(address _address) public view returns (uint256 _token) {
        return tokenClaimedOnThisChain[_address];
    }

    function setTokenSentToLinkedChain(address _address, uint256 _token) public onlyBridge {
        tokenSentToLinkedChain[_address] = _token;
        tokenSentToLinkedChainTime[_address] = now;
        emit TokenSentToLinkedChain(_address, _token, tokenSentToLinkedChain[_address], getBalanceHash(_address, tokenSentToLinkedChain[_address]));
    }

    function getTokenSentToLinkedChain(address _address) public view returns (uint256 _token) {
        return tokenSentToLinkedChain[_address];
    }

    function getTokenSentToLinkedChainTime(address _address) public view returns (uint256 _timeStamp) {
        return tokenSentToLinkedChainTime[_address];
    }

    function add24HoursWithdrawn(uint256 _amount) public onlyBridge {
        last24HoursAmountWithdrawn = last24HoursAmountWithdrawn.add(_amount);
        emit RollingWithdrawnAmountUpdated(last24HoursAmountWithdrawn, lastWithdrawLimitReductionTime);
    }

    function update24HoursWithdrawLimit(uint256 _amount) public onlyBridge {
        if (last24HoursAmountWithdrawn > _amount) {
            last24HoursAmountWithdrawn = last24HoursAmountWithdrawn.sub(_amount);
        } else {
            last24HoursAmountWithdrawn = 0;
        }
        lastWithdrawLimitReductionTime = now;
        emit RollingWithdrawnAmountUpdated(last24HoursAmountWithdrawn, lastWithdrawLimitReductionTime);
    }

    function set24HourWithdrawLimit(uint256 _limit) public onlyBridge {
        withdrawLimit24Hours = _limit;
        emit WithdrawLimitUpdated(_limit);
    }

    function resetLast24HoursAmountWithdrawn() public onlyBridge {
        last24HoursAmountWithdrawn = 0;
        emit Last24HoursAmountWithdrawnReset();
    }

    function setInactivityPeriod(uint256 _periodLength) public onlyBridge {
        inactivityPeriod = _periodLength;
        emit InactivityPeriodUpdated(_periodLength);
    }

    function getBridgeNonce() public onlyBridge returns (uint256 _nonce) {
        transferNonce++;
        emit NewBridgeNonce(transferNonce);
        return transferNonce;
    }

    function disableFastWithdraws() public onlyBridge {
        fastTransfersEnabled = false;
        emit FastWithdrawsDisabled();
    }

    function setPositionClaimedOnMainChain(bytes32 _positionHash) public onlyBridge {
        positionClaimedOnMainChain[_positionHash] = true;
    }

    function getPositionClaimedOnMainChain(bytes32 _positionHash) public view returns (bool _alreadyClaimed) {
        return positionClaimedOnMainChain[_positionHash];
    }

    // ----------------------------------------------------------------------------
    // Setter/Getter functions for spam protection
    // ----------------------------------------------------------------------------

    function setLastRequestBlock(address _address) public onlyPlatform {
        lastRequestBlock[_address] = block.number;
    }

    function getLastRequestBlock(address _address) public view returns(uint256 _lastRequestBlock) {
        return lastRequestBlock[_address];
    }

    function setNumberOfRequests(address _address, uint256 _numberOfRequests) public onlyPlatform {
        numberOfRequests[_address] = _numberOfRequests;
    }

    function increaseNumberOfRequests(address _address) public onlyPlatform{
        numberOfRequests[_address]++;
    }

    function getNumberOfRequests(address _address) public view returns(uint256 _numberOfRequests) {
        return numberOfRequests[_address];
    }

    function setNumberOfRequestsLimit(uint256 _numberOfRequestsLimit) public onlyPlatform {
        numberOfRequestsLimit = _numberOfRequestsLimit;
        emit NumberOfRequestsLimitUpdate(_numberOfRequestsLimit);
    }

    function getNumberOfRequestsLimit() public view returns (uint256 _numberOfRequestsLimit) {
        return numberOfRequestsLimit;
    }

    function setMainChainWithdrawLimit(uint256 _mainChainWithdrawLimit24) public onlyOwner {
        mainChainWithdrawLimit24 = _mainChainWithdrawLimit24;
        emit MainChainWithdrawLimitUpdate(_mainChainWithdrawLimit24);
    }

    function getMainChainWithdrawLimit() public view returns (uint256 _mainChainWithdrawLimit24) {
        return mainChainWithdrawLimit24;
    }

    // ----------------------------------------------------------------------------
    // Setter/Getter functions for state access
    // ----------------------------------------------------------------------------

    function grantAccess(address _address) public onlyOwner {
        stateAccess[_address] = true;
        emit StateAccessGranted(_address, block.number);
    }

    function denyAccess(address _address) public onlyOwner {
        stateAccess[_address] = false;
        emit StateAccessDenied(_address, block.number);
    }

    function getStateAccess(address _address) public view returns(bool _hasAccess) {
        return stateAccess[_address];
    }

    // ----------------------------------------------------------------------------
    // Setter/Getter functions for addresses that can transfer tokens (sidechain only)
    // ----------------------------------------------------------------------------

    function enableTransfers(address _address) public onlyOwner {
        transferAllowed[_address] = true;
        emit TransfersEnabled(_address);
    }

    function disableTransfers(address _address) public onlyOwner {
        transferAllowed[_address] = false;
        emit TransfersDisabled(_address);
    }

    function getCanTransfer(address _address) public view returns(bool _hasAccess) {
        return transferAllowed[_address];
    }

    // ----------------------------------------------------------------------------
    // Minting/burning/transfer of token
    // ----------------------------------------------------------------------------

    function transfer(address _from, address _to, uint256 _token) public onlyPlatform notPaused {
        require(balances[_from] >= _token, "MorpherState: Not enough token.");
        balances[_from] = balances[_from].sub(_token);
        balances[_to] = balances[_to].add(_token);
        IMorpherToken(morpherToken).emitTransfer(_from, _to, _token);
        emit Transfer(_from, _to, _token);
        emit SetBalance(_from, balances[_from], getBalanceHash(_from, balances[_from]));
        emit SetBalance(_to, balances[_to], getBalanceHash(_to, balances[_to]));
    }

    function mint(address _address, uint256 _token) public onlyPlatform notPaused {
        balances[_address] = balances[_address].add(_token);
        totalToken = totalToken.add(_token);
        updateTotalSupply();
        IMorpherToken(morpherToken).emitTransfer(address(0), _address, _token);
        emit Mint(_address, _token, totalToken);
        emit SetBalance(_address, balances[_address], getBalanceHash(_address, balances[_address]));
    }

    function burn(address _address, uint256 _token) public onlyPlatform notPaused {
        require(balances[_address] >= _token, "MorpherState: Not enough token.");
        balances[_address] = balances[_address].sub(_token);
        totalToken = totalToken.sub(_token);
        updateTotalSupply();
        IMorpherToken(morpherToken).emitTransfer(_address, address(0), _token);
        emit Burn(_address, _token, totalToken);
        emit SetBalance(_address, balances[_address], getBalanceHash(_address, balances[_address]));
    }

    // ----------------------------------------------------------------------------
    // Setter/Getter functions for balance and token functions (ERC20)
    // ----------------------------------------------------------------------------
    function updateTotalSupply() private {
        totalSupply = totalToken.add(totalInPositions).add(totalOnOtherChain);
        emit NewTotalSupply(totalSupply);
    }

    function setTotalInPositions(uint256 _totalInPositions) public onlyAdministrator {
        totalInPositions = _totalInPositions;
        updateTotalSupply();
        emit NewTotalInPositions(_totalInPositions);
    }

    function setTotalOnOtherChain(uint256 _newTotalOnOtherChain) public onlySideChainOperator {
        totalOnOtherChain = _newTotalOnOtherChain;
        updateTotalSupply();
        emit NewTotalOnOtherChain(_newTotalOnOtherChain);
    }

    function balanceOf(address _tokenOwner) public view returns (uint256 balance) {
        return balances[_tokenOwner];
    }

    function setAllowance(address _from, address _spender, uint256 _tokens) public onlyPlatform {
        allowed[_from][_spender] = _tokens;
        emit SetAllowance(_from, _spender, _tokens);
    }

    function getAllowance(address _tokenOwner, address spender) public view returns (uint256 remaining) {
        return allowed[_tokenOwner][spender];
    }

    // ----------------------------------------------------------------------------
    // Setter/Getter functions for platform roles
    // ----------------------------------------------------------------------------

    function setGovernanceContract(address _newGovernanceContractAddress) public onlyOwner {
        morpherGovernance = _newGovernanceContractAddress;
        emit GovernanceChange(_newGovernanceContractAddress);
    }

    function getGovernance() public view returns (address _governanceContract) {
        return morpherGovernance;
    }

    function setMorpherBridge(address _newBridge) public onlyOwner {
        morpherBridge = _newBridge;
        emit BridgeChange(_newBridge);
    }

    function getMorpherBridge() public view returns (address _currentBridge) {
        return morpherBridge;
    }

    function setOracleContract(address _newOracleContract) public onlyGovernance {
        oracleContract = _newOracleContract;
        emit OracleChange(_newOracleContract);
    }

    function getOracleContract() public view returns(address) {
        return oracleContract;
    }

    function setTokenContract(address _newTokenContract) public onlyOwner {
        morpherToken = _newTokenContract;
        emit TokenChange(_newTokenContract);
    }

    function getTokenContract() public view returns(address) {
        return morpherToken;
    }

    function setAdministrator(address _newAdministrator) public onlyGovernance {
        administrator = _newAdministrator;
        emit AdministratorChange(_newAdministrator);
    }

    function getAdministrator() public view returns(address) {
        return administrator;
    }

    // ----------------------------------------------------------------------------
    // Setter/Getter functions for platform operating rewards
    // ----------------------------------------------------------------------------

    function setRewardAddress(address _newRewardsAddress) public onlyOwner {
        morpherRewards = _newRewardsAddress;
        emit RewardsChange(_newRewardsAddress, rewardBasisPoints);
    }

    function setRewardBasisPoints(uint256 _newRewardBasisPoints) public onlyOwner {
        if (mainChain == true) {
            require(_newRewardBasisPoints <= 15000, "MorpherState: Reward basis points need to be less or equal to 15000.");
        } else {
            require(_newRewardBasisPoints == 0, "MorpherState: Reward basis points can only be set on Ethereum.");
        }
        rewardBasisPoints = _newRewardBasisPoints;
        emit RewardsChange(morpherRewards, _newRewardBasisPoints);
    }

    function setLastRewardTime(uint256 _lastRewardTime) private {
        lastRewardTime = _lastRewardTime;
        emit LastRewardTime(_lastRewardTime);
    }

    // ----------------------------------------------------------------------------
    // Setter/Getter functions for platform administration
    // ----------------------------------------------------------------------------

    function activateMarket(bytes32 _activateMarket) public onlyAdministrator {
        marketActive[_activateMarket] = true;
        emit MarketActivated(_activateMarket);
    }

    function deActivateMarket(bytes32 _deActivateMarket) public onlyAdministrator {
        marketActive[_deActivateMarket] = false;
        emit MarketDeActivated(_deActivateMarket);
    }

    function getMarketActive(bytes32 _marketId) public view returns(bool _active) {
        return marketActive[_marketId];
    }

    function setMaximumLeverage(uint256 _newMaximumLeverage) public onlyAdministrator {
        require(_newMaximumLeverage > PRECISION, "MorpherState: Leverage precision is 1e8");
        maximumLeverage = _newMaximumLeverage;
        emit MaximumLeverageChange(_newMaximumLeverage);
    }

    function getMaximumLeverage() public view returns(uint256 _maxLeverage) {
        return maximumLeverage;
    }

    function pauseState() public onlyAdministrator {
        paused = true;
        emit StatePaused(msg.sender, true);
    }

    function unPauseState() public onlyAdministrator {
        paused = false;
        emit StatePaused(msg.sender, false);
    }

    // ----------------------------------------------------------------------------
    // Setter/Getter for side chain state
    // ----------------------------------------------------------------------------

    function setSideChainMerkleRoot(bytes32 _sideChainMerkleRoot) public onlyBridge {
        sideChainMerkleRoot = _sideChainMerkleRoot;
        sideChainMerkleRootWrittenAtTime = now;
        payOperatingReward;
        emit SideChainMerkleRootUpdate(_sideChainMerkleRoot);
    }

    function getSideChainMerkleRoot() public view returns(bytes32 _sideChainMerkleRoot) {
        return sideChainMerkleRoot;
    }

    function setSideChainOperator(address _address) public onlyOwner {
        sideChainOperator = _address;
        emit NewSideChainOperator(_address);
    }

    function getSideChainOperator() public view returns (address _address) {
        return sideChainOperator;
    }

    function getSideChainMerkleRootWrittenAtTime() public view returns(uint256 _sideChainMerkleRoot) {
        return sideChainMerkleRootWrittenAtTime;
    }

    // ----------------------------------------------------------------------------
    // Setter/Getter functions for portfolio
    // ----------------------------------------------------------------------------

    function setPosition(
        address _address,
        bytes32 _marketId,
        uint256 _timeStamp,
        uint256 _longShares,
        uint256 _shortShares,
        uint256 _meanEntryPrice,
        uint256 _meanEntrySpread,
        uint256 _meanEntryLeverage,
        uint256 _liquidationPrice
    ) public onlyPlatform {
        portfolio[_address][_marketId].lastUpdated = _timeStamp;
        portfolio[_address][_marketId].longShares = _longShares;
        portfolio[_address][_marketId].shortShares = _shortShares;
        portfolio[_address][_marketId].meanEntryPrice = _meanEntryPrice;
        portfolio[_address][_marketId].meanEntrySpread = _meanEntrySpread;
        portfolio[_address][_marketId].meanEntryLeverage = _meanEntryLeverage;
        portfolio[_address][_marketId].liquidationPrice = _liquidationPrice;
        portfolio[_address][_marketId].positionHash = getPositionHash(
            _address,
            _marketId,
            _timeStamp,
            _longShares,
            _shortShares,
            _meanEntryPrice,
            _meanEntrySpread,
            _meanEntryLeverage,
            _liquidationPrice
        );
        if (_longShares > 0 || _shortShares > 0) {
            addExposureByMarket(_marketId, _address);
        } else {
            deleteExposureByMarket(_marketId, _address);
        }
        emit SetPosition(
            portfolio[_address][_marketId].positionHash,
            _address,
            _marketId,
            _timeStamp,
            _longShares,
            _shortShares,
            _meanEntryPrice,
            _meanEntrySpread,
            _meanEntryLeverage,
            _liquidationPrice
        );
    }

    function getPosition(
        address _address,
        bytes32 _marketId
    ) public view returns (
        uint256 _longShares,
        uint256 _shortShares,
        uint256 _meanEntryPrice,
        uint256 _meanEntrySpread,
        uint256 _meanEntryLeverage,
        uint256 _liquidationPrice
    ) {
        return(
        portfolio[_address][_marketId].longShares,
        portfolio[_address][_marketId].shortShares,
        portfolio[_address][_marketId].meanEntryPrice,
        portfolio[_address][_marketId].meanEntrySpread,
        portfolio[_address][_marketId].meanEntryLeverage,
        portfolio[_address][_marketId].liquidationPrice
        );
    }

    function getPositionHash(
        address _address,
        bytes32 _marketId,
        uint256 _timeStamp,
        uint256 _longShares,
        uint256 _shortShares,
        uint256 _meanEntryPrice,
        uint256 _meanEntrySpread,
        uint256 _meanEntryLeverage,
        uint256 _liquidationPrice
    ) public pure returns (bytes32 _hash) {
        return keccak256(
            abi.encodePacked(
                _address,
                _marketId,
                _timeStamp,
                _longShares,
                _shortShares,
                _meanEntryPrice,
                _meanEntrySpread,
                _meanEntryLeverage,
                _liquidationPrice
            )
        );
    }

    function getBalanceHash(address _address, uint256 _balance) public pure returns (bytes32 _hash) {
        return keccak256(abi.encodePacked(_address, _balance));
    }

    function getLastUpdated(address _address, bytes32 _marketId) public view returns (uint256 _lastUpdated) {
        return(portfolio[_address][_marketId].lastUpdated);
    }

    function getLongShares(address _address, bytes32 _marketId) public view returns (uint256 _longShares) {
        return(portfolio[_address][_marketId].longShares);
    }

    function getShortShares(address _address, bytes32 _marketId) public view returns (uint256 _shortShares) {
        return(portfolio[_address][_marketId].shortShares);
    }

    function getMeanEntryPrice(address _address, bytes32 _marketId) public view returns (uint256 _meanEntryPrice) {
        return(portfolio[_address][_marketId].meanEntryPrice);
    }

    function getMeanEntrySpread(address _address, bytes32 _marketId) public view returns (uint256 _meanEntrySpread) {
        return(portfolio[_address][_marketId].meanEntrySpread);
    }

    function getMeanEntryLeverage(address _address, bytes32 _marketId) public view returns (uint256 _meanEntryLeverage) {
        return(portfolio[_address][_marketId].meanEntryLeverage);
    }

    function getLiquidationPrice(address _address, bytes32 _marketId) public view returns (uint256 _liquidationPrice) {
        return(portfolio[_address][_marketId].liquidationPrice);
    }

    // ----------------------------------------------------------------------------
    // Record positions by market by address. Needed for exposure aggregations
    // and spits and dividends.
    // ----------------------------------------------------------------------------
    function addExposureByMarket(bytes32 _symbol, address _address) private {
        // Address must not be already recored
        uint256 _myExposureIndex = getExposureMappingIndex(_symbol, _address);
        if (_myExposureIndex == 0) {
            uint256 _maxMappingIndex = getMaxMappingIndex(_symbol).add(1);
            setMaxMappingIndex(_symbol, _maxMappingIndex);
            setExposureMapping(_symbol, _address, _maxMappingIndex);
        }
    }

    function deleteExposureByMarket(bytes32 _symbol, address _address) private {
        // Get my index in mapping
        uint256 _myExposureIndex = getExposureMappingIndex(_symbol, _address);
        // Get last element of mapping
        uint256 _lastIndex = getMaxMappingIndex(_symbol);
        address _lastAddress = getExposureMappingAddress(_symbol, _lastIndex);
        // If _myExposureIndex is greater than 0 (i.e. there is an exposure of that address on that market) delete it
        if (_myExposureIndex > 0) {
            // If _myExposureIndex is less than _lastIndex overwrite element at _myExposureIndex with element at _lastIndex in
            // deleted elements position.
            if (_myExposureIndex < _lastIndex) {
                setExposureMappingAddress(_symbol, _lastAddress, _myExposureIndex);
                setExposureMappingIndex(_symbol, _lastAddress, _myExposureIndex);
            }
            // Delete _lastIndex and _lastAddress element and reduce maxExposureIndex
            setExposureMappingAddress(_symbol, address(0), _lastIndex);
            setExposureMappingIndex(_symbol, _address, 0);
            // Shouldn't happen, but check that not empty
            if (_lastIndex > 0) {
                setMaxMappingIndex(_symbol, _lastIndex.sub(1));
            }
        }
    }

    // ----------------------------------------------------------------------------
    // Calculate and send operating reward
    // Every 24 hours the protocol mints rewardBasisPoints/(PRECISION) percent of the total
    // supply as reward for the protocol operator. The amount can not exceed 0.015% per
    // day.
    // ----------------------------------------------------------------------------

    function payOperatingReward() public onlyMainChain {
        if (now > lastRewardTime.add(REWARDPERIOD)) {
            uint256 _reward = totalSupply.mul(rewardBasisPoints).div(PRECISION);
            setLastRewardTime(lastRewardTime.add(REWARDPERIOD));
            mint(morpherRewards, _reward);
            emit OperatingRewardMinted(morpherRewards, _reward);
        }
    }
}

File 2 of 15: IERC20.sol
pragma solidity 0.5.16;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
 * the optional functions; to access them see {ERC20Detailed}.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 3 of 15: IMorpherToken.sol
pragma solidity 0.5.16;

interface IMorpherToken {
    /**
     * Emits a {Transfer} event in ERC-20 token contract.
     */
    function emitTransfer(address _from, address _to, uint256 _amount) external;
}

File 4 of 15: MerkleProof.sol
pragma solidity 0.5.16;

/**
 * @dev These functions deal with verification of Merkle trees (hash trees),
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
        require(proof.length < 100, "MerkleProof: proof too long. Use only sibling hashes.");
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            bytes32 proofElement = proof[i];

            if (computedHash < proofElement) {
                // Hash(current computed hash + current element of the proof)
                computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
            } else {
                // Hash(current element of the proof + current computed hash)
                computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
            }
        }

        // Check if the computed hash (root) is equal to the provided root
        return computedHash == root;
    }
}

File 5 of 15: Migrations.sol
pragma solidity 0.5.16;

contract Migrations {
  address public owner;
  uint public last_completed_migration;

  modifier restricted() {
    if (msg.sender == owner) _;
  }

  constructor() public {
    owner = msg.sender;
  }

  function setCompleted(uint completed) public restricted {
    last_completed_migration = completed;
  }

  function upgrade(address new_address) public restricted {
    Migrations upgraded = Migrations(new_address);
    upgraded.setCompleted(last_completed_migration);
  }
}

File 6 of 15: MorpherAdmin.sol
pragma solidity 0.5.16;

import "./SafeMath.sol";
import "./MorpherState.sol";
import "./MorpherTradeEngine.sol";

// ----------------------------------------------------------------------------------
// Administrator of the Morpher platform
// ----------------------------------------------------------------------------------

contract MorpherAdmin {
    MorpherState state;
    MorpherTradeEngine tradeEngine;
    using SafeMath for uint256;

// ----------------------------------------------------------------------------
// Precision of prices and leverage
// ----------------------------------------------------------------------------

    modifier onlyAdministrator {
        require(msg.sender == state.getAdministrator(), "Function can only be called by the Administrator.");
        _;
    }
    
    constructor(address _stateAddress, address _tradeEngine) public {
        state = MorpherState(_stateAddress);
        tradeEngine = MorpherTradeEngine(_tradeEngine);
    }

// ----------------------------------------------------------------------------
// Administrative functions
// Set state address and maximum permitted leverage on platform
// ----------------------------------------------------------------------------
    function setMorpherState(address _stateAddress) public onlyAdministrator {
        state = MorpherState(_stateAddress);
    }

    function setMorpherTradeEngine(address _tradeEngine) public onlyAdministrator {
        tradeEngine = MorpherTradeEngine(_tradeEngine);
    }

// ----------------------------------------------------------------------------------
// stockSplits(bytes32 _marketId, uint256 _fromIx, uint256 _toIx, uint256 _nominator, uint256 _denominator)
// Experimental and untested
// ----------------------------------------------------------------------------------

    function stockSplits(bytes32 _marketId, uint256 _fromIx, uint256 _toIx, uint256 _nominator, uint256 _denominator) public onlyAdministrator {
        require(state.getMarketActive(_marketId) == false, "Market must be paused to process stock splits.");
        // If no _fromIx and _toIx specified, do entire _list
        if (_fromIx == 0) {
            _fromIx = 1;
        }
        if (_toIx == 0) {
            _toIx = state.getMaxMappingIndex(_marketId);
        }
        uint256 _positionLongShares;
        uint256 _positionShortShares;
        uint256 _positionAveragePrice;
        uint256 _positionAverageSpread;
        uint256 _positionAverageLeverage;
        uint256 _liquidationPrice;
        address _address;
        
        for (uint256 i = _fromIx; i <= _toIx; i++) {
             // GET position from state
             // multiply with nominator, divide by denominator (longShares/shortShares/meanEntry/meanSpread)
             // Write back to state
            _address = state.getExposureMappingAddress(_marketId, i);
            (_positionLongShares, _positionShortShares, _positionAveragePrice, _positionAverageSpread, _positionAverageLeverage, _liquidationPrice) = state.getPosition(_address, _marketId);
            _positionLongShares      = _positionLongShares.mul(_denominator).div(_nominator);
            _positionShortShares     = _positionShortShares.mul(_denominator).div(_nominator);
            _positionAveragePrice    = _positionAveragePrice.mul(_nominator).div(_denominator);
            _positionAverageSpread   = _positionAverageSpread.mul(_nominator).div(_denominator);
            if (_positionShortShares > 0) {
                _liquidationPrice    = tradeEngine.getLiquidationPrice(_positionAveragePrice, _positionAverageLeverage, false);
            } else {
                _liquidationPrice    = tradeEngine.getLiquidationPrice(_positionAveragePrice, _positionAverageLeverage, true);
            }               
            state.setPosition(_address, _marketId, now, _positionLongShares, _positionShortShares, _positionAveragePrice, _positionAverageSpread, _positionAverageLeverage, _liquidationPrice);   
        }
    }

// ----------------------------------------------------------------------------------
// contractRolls(bytes32 _marketId, uint256 _fromIx, uint256 _toIx, uint256 _rollUp, uint256 _rollDown)
// Experimental and untested
// ----------------------------------------------------------------------------------
    function contractRolls(bytes32 _marketId, uint256 _fromIx, uint256 _toIx, uint256 _rollUp, uint256 _rollDown) public onlyAdministrator {
        // If no _fromIx and _toIx specified, do entire _list
        // dividends set meanEntry down, rolls either up or down
        require(state.getMarketActive(_marketId) == false, "Market must be paused to process rolls.");
        // If no _fromIx and _toIx specified, do entire _list
        if (_fromIx == 0) {
            _fromIx = 1;
        }
        if (_toIx == 0) {
            _toIx = state.getMaxMappingIndex(_marketId);
        }
        uint256 _positionLongShares;
        uint256 _positionShortShares;
        uint256 _positionAveragePrice;
        uint256 _positionAverageSpread;
        uint256 _positionAverageLeverage;
        uint256 _liquidationPrice;
        address _address;
        
        for (uint256 i = _fromIx; i <= _toIx; i++) {
             // GET position from state
             // shift by _upMove and _downMove (one of them is supposed to be zero)
             // Write back to state
            _address = state.getExposureMappingAddress(_marketId, i);
            (_positionLongShares, _positionShortShares, _positionAveragePrice, _positionAverageSpread, _positionAverageLeverage, _liquidationPrice) = state.getPosition(_address, _marketId);
            _positionAveragePrice    = _positionAveragePrice.add(_rollUp).sub(_rollDown);
            if (_positionShortShares > 0) {
                _liquidationPrice    = tradeEngine.getLiquidationPrice(_positionAveragePrice, _positionAverageLeverage, false);
            } else {
                _liquidationPrice    = tradeEngine.getLiquidationPrice(_positionAveragePrice, _positionAverageLeverage, true);
            }               
            state.setPosition(_address, _marketId, now, _positionLongShares, _positionShortShares, _positionAveragePrice, _positionAverageSpread, _positionAverageLeverage, _liquidationPrice);   
        }
    }

// ----------------------------------------------------------------------------------
// stockDividends()
// May want to add support for dividends later
// ----------------------------------------------------------------------------------
/*    function stockDividends(bytes32 _marketId, uint256 _fromIx, uint256 _toIx, uint256 _meanEntryUp, uint256 _meanEntryDown) public onlyOracle returns (bool _success){
    }
*/
}

File 7 of 15: MorpherAirdrop.sol
pragma solidity 0.5.16;

import "./Ownable.sol";
import "./SafeMath.sol";
import "./IERC20.sol";

// ----------------------------------------------------------------------------------
// Holds the Airdrop Token balance on contract address
// AirdropAdmin can authorize addresses to receive airdrop.
// Users have to claim their airdrop actively or Admin initiates transfer.
// ----------------------------------------------------------------------------------

contract MorpherAirdrop is Ownable {
    using SafeMath for uint256;

// ----------------------------------------------------------------------------
// Mappings for authorized / claimed airdrop
// ----------------------------------------------------------------------------
    mapping(address => uint256) private airdropClaimed;
    mapping(address => uint256) private airdropAuthorized;

    uint256 public totalAirdropAuthorized;
    uint256 public totalAirdropClaimed;

    address public airdropAdmin;
    address public morpherToken;

// ----------------------------------------------------------------------------
// Events
// ----------------------------------------------------------------------------
    event AirdropSent(address indexed _operator, address indexed _recipient, uint256 _amountClaimed, uint256 _amountAuthorized);
    event SetAirdropAuthorized(address indexed _recipient, uint256 _amountClaimed, uint256 _amountAuthorized);

    constructor(address _airdropAdminAddress, address _morpherToken, address _coldStorageOwnerAddress) public {
        setAirdropAdmin(_airdropAdminAddress);
        setMorpherTokenAddress(_morpherToken);
        transferOwnership(_coldStorageOwnerAddress);
    }

    modifier onlyAirdropAdmin {
        require(msg.sender == airdropAdmin, "MorpherAirdrop: can only be called by Airdrop Administrator.");
        _;
    }

// ----------------------------------------------------------------------------
// Administrative functions
// ----------------------------------------------------------------------------
    function setAirdropAdmin(address _address) public onlyOwner {
        airdropAdmin = _address;
    }

    function setMorpherTokenAddress(address _address) public onlyOwner {
        morpherToken = _address;
    }

// ----------------------------------------------------------------------------
// Get airdrop amount authorized for or claimed by address
// ----------------------------------------------------------------------------
    function getAirdropClaimed(address _userAddress) public view returns (uint256 _amount) {
        return airdropClaimed[_userAddress];
    }

    function getAirdropAuthorized(address _userAddress) public view returns (uint256 _balance) {
        return airdropAuthorized[_userAddress];
    }

    function getAirdrop(address _userAddress) public view returns(uint256 _claimed, uint256 _authorized) {
        return (airdropClaimed[_userAddress], airdropAuthorized[_userAddress]);
    }

// ----------------------------------------------------------------------------
// Airdrop Administrator can authorize airdrop amount per address
// ----------------------------------------------------------------------------
    function setAirdropAuthorized(address _userAddress, uint256 _authorized) public onlyAirdropAdmin {
        // Can only set authorized amount to be higher than claimed
        require(_authorized >= airdropClaimed[_userAddress], "MorpherAirdrop: airdrop authorized must be larger than claimed.");
        // Authorized amount can be higher or lower than previously authorized amount, adjust accordingly
        totalAirdropAuthorized = totalAirdropAuthorized.sub(getAirdropAuthorized(_userAddress)).add(_authorized);
        airdropAuthorized[_userAddress] = _authorized;
        emit SetAirdropAuthorized(_userAddress, airdropClaimed[_userAddress], _authorized);
    }

// ----------------------------------------------------------------------------
// User claims their entire airdrop
// ----------------------------------------------------------------------------
    function claimAirdrop() public {
        uint256 _amount = airdropAuthorized[msg.sender].sub(airdropClaimed[msg.sender]);
        _sendAirdrop(msg.sender, _amount);
    }

// ----------------------------------------------------------------------------
// User claims part of their airdrop
// ----------------------------------------------------------------------------
    function claimSomeAirdrop(uint256 _amount) public {
        _sendAirdrop(msg.sender, _amount);
    }

// ----------------------------------------------------------------------------
// Administrator sends user their entire airdrop
// ----------------------------------------------------------------------------
    function adminSendAirdrop(address _recipient) public onlyAirdropAdmin {
        uint256 _amount = airdropAuthorized[_recipient].sub(airdropClaimed[_recipient]);
        _sendAirdrop(_recipient, _amount);
    }

// ----------------------------------------------------------------------------
// Administrator sends user part of their airdrop
// ----------------------------------------------------------------------------
    function adminSendSomeAirdrop(address _recipient, uint256 _amount) public onlyAirdropAdmin {
        _sendAirdrop(_recipient, _amount);
    }

// ----------------------------------------------------------------------------
// Administrator sends user entire airdrop
// ----------------------------------------------------------------------------
    function _sendAirdrop(address _recipient, uint256 _amount) private {
        require(airdropAuthorized[_recipient] >= airdropClaimed[_recipient].add(_amount), "MorpherAirdrop: amount exceeds authorized airdrop amount.");
        airdropClaimed[_recipient] = airdropClaimed[_recipient].add(_amount);
        totalAirdropClaimed = totalAirdropClaimed.add(_amount);
        IERC20(morpherToken).transfer(_recipient, _amount);
        emit AirdropSent(msg.sender, _recipient, airdropClaimed[_recipient], airdropAuthorized[_recipient]);
    }

// ----------------------------------------------------------------------------
// Administrator sends user part of their airdrop
// ----------------------------------------------------------------------------
    function adminAuthorizeAndSend(address _recipient, uint256 _amount) public onlyAirdropAdmin {
        setAirdropAuthorized(_recipient, getAirdropAuthorized(_recipient).add(_amount));
        _sendAirdrop(_recipient, _amount);
    }

// ------------------------------------------------------------------------
// Don't accept ETH
// ------------------------------------------------------------------------
    function () external payable {
        revert("MorpherAirdrop: you can't deposit Ether here");
    }
}

File 8 of 15: MorpherBridge.sol
// ------------------------------------------------------------------------
// MorpherBridge
// Handles deposit to and withdraws from the side chain, writing of the merkle
// root to the main chain by the side chain operator, and enforces a rolling 24 hours
// token withdraw limit from side chain to main chain.
// If side chain operator doesn't write a merkle root hash to main chain for more than
// 72 hours positions and balaces from side chain can be transferred to main chain.
// ------------------------------------------------------------------------

pragma solidity 0.5.16;

import "./Ownable.sol";
import "./SafeMath.sol";
import "./MorpherState.sol";
import "./MerkleProof.sol";

contract MorpherBridge is Ownable {

    MorpherState state;
    using SafeMath for uint256;

    event TransferToLinkedChain(
        address indexed from,
        uint256 tokens,
        uint256 totalTokenSent,
        uint256 timeStamp,
        uint256 transferNonce,
        bytes32 indexed transferHash
    );
    event TrustlessWithdrawFromSideChain(address indexed from, uint256 tokens);
    event OperatorChainTransfer(address indexed from, uint256 tokens, bytes32 sidechainTransactionHash);
    event ClaimFailedTransferToSidechain(address indexed from, uint256 tokens);
    event PositionRecoveryFromSideChain(address indexed from, bytes32 positionHash);
    event TokenRecoveryFromSideChain(address indexed from, bytes32 positionHash);
    event SideChainMerkleRootUpdated(bytes32 _rootHash);
    event WithdrawLimitReset();
    event WithdrawLimitChanged(uint256 _withdrawLimit);
    event LinkState(address _address);

    constructor(address _stateAddress, address _coldStorageOwnerAddress) public {
        setMorpherState(_stateAddress);
        transferOwnership(_coldStorageOwnerAddress);
    }

    modifier onlySideChainOperator {
        require(msg.sender == state.getSideChainOperator(), "MorpherBridge: Function can only be called by Sidechain Operator.");
        _;
    }

    modifier sideChainInactive {
        require(now - state.inactivityPeriod() > state.getSideChainMerkleRootWrittenAtTime(), "MorpherBridge: Function can only be called if sidechain is inactive.");
        _;
    }
    
    modifier fastTransfers {
        require(state.fastTransfersEnabled() == true, "MorpherBridge: Fast transfers have been disabled permanently.");
        _;
    }

    modifier onlyMainchain {
        require(state.mainChain() == true, "MorpherBridge: Function can only be executed on Ethereum." );
        _;
    }
    
    // ------------------------------------------------------------------------
    // Links Token Contract with State
    // ------------------------------------------------------------------------
    function setMorpherState(address _stateAddress) public onlyOwner {
        state = MorpherState(_stateAddress);
        emit LinkState(_stateAddress);
    }

    function setInactivityPeriod(uint256 _periodInSeconds) private {
        state.setInactivityPeriod(_periodInSeconds);
    }

    function disableFastTransfers() public onlyOwner  {
        state.disableFastWithdraws();
    }

    function updateSideChainMerkleRoot(bytes32 _rootHash) public onlySideChainOperator {
        state.setSideChainMerkleRoot(_rootHash);
        emit SideChainMerkleRootUpdated(_rootHash);
    }

    function resetLast24HoursAmountWithdrawn() public onlySideChainOperator {
        state.resetLast24HoursAmountWithdrawn();
        emit WithdrawLimitReset();
    }

    function set24HourWithdrawLimit(uint256 _withdrawLimit) public onlySideChainOperator {
        state.set24HourWithdrawLimit(_withdrawLimit);
        emit WithdrawLimitChanged(_withdrawLimit);
    }

    function getTokenSentToLinkedChain(address _address) public view returns (uint256 _token) {
        return state.getTokenSentToLinkedChain(_address);
    }

    function getTokenClaimedOnThisChain(address _address) public view returns (uint256 _token)  {
        return state.getTokenClaimedOnThisChain(_address);
    }

    function getTokenSentToLinkedChainTime(address _address) public view returns (uint256 _time)  {
        return state.getTokenSentToLinkedChainTime(_address);
    }

    // ------------------------------------------------------------------------
    // verifyWithdrawOk(uint256 _amount)
    // Checks if creating _amount token on main chain does not violate the 24 hour transfer limit
    // ------------------------------------------------------------------------
    function verifyWithdrawOk(uint256 _amount) public returns (bool _authorized) {
        uint256 _lastWithdrawLimitReductionTime = state.lastWithdrawLimitReductionTime();
        uint256 _withdrawLimit24Hours = state.withdrawLimit24Hours();
        
        if (now > _lastWithdrawLimitReductionTime) {
            uint256 _timePassed = now.sub(_lastWithdrawLimitReductionTime);
            state.update24HoursWithdrawLimit(_timePassed.mul(_withdrawLimit24Hours).div(1 days));
        }
        
        if (state.last24HoursAmountWithdrawn().add(_amount) <= _withdrawLimit24Hours) {
            return true;
        } else {
            return false;
        }
    }

    // ------------------------------------------------------------------------
    // transferToSideChain(uint256 _tokens)
    // Transfer token to Morpher's side chain to trade without fees and near instant
    // settlement.
    // - Owner's account must have sufficient balance to transfer
    // - 0 value transfers are not supported
    // Token are burned on the main chain and are created and credited to msg.sender
    //  on the side chain
    // ------------------------------------------------------------------------
    function transferToSideChain(uint256 _tokens) public {
        require(_tokens >= 0, "MorpherBridge: Amount of tokens must be positive.");
        require(state.balanceOf(msg.sender) >= _tokens, "MorpherBridge: Insufficient balance.");
        state.burn(msg.sender, _tokens);
        uint256 _newTokenSentToLinkedChain = getTokenSentToLinkedChain(msg.sender).add(_tokens);
        uint256 _transferNonce = state.getBridgeNonce();
        uint256 _timeStamp = now;
        bytes32 _transferHash = keccak256(
            abi.encodePacked(
                msg.sender,
                _tokens,
                _newTokenSentToLinkedChain,
                _timeStamp,
                _transferNonce
            )
        );
        state.setTokenSentToLinkedChain(msg.sender, _newTokenSentToLinkedChain);
        emit TransferToLinkedChain(msg.sender, _tokens, _newTokenSentToLinkedChain, _timeStamp, _transferNonce, _transferHash);
    }

    // ------------------------------------------------------------------------
    // fastTransferFromSideChain(uint256 _numOfToken, uint256 _tokenBurnedOnLinkedChain, bytes32[] memory _proof)
    // The sidechain operator can credit users with token they burend on the sidechain. Transfers
    // happen immediately. To be removed after Beta.
    // ------------------------------------------------------------------------
    function fastTransferFromSideChain(address _address, uint256 _numOfToken, uint256 _tokenBurnedOnLinkedChain, bytes32 _sidechainTransactionHash) public onlySideChainOperator fastTransfers {
        uint256 _tokenClaimed = state.getTokenClaimedOnThisChain(_address);
        require(verifyWithdrawOk(_numOfToken), "MorpherBridge: Withdraw amount exceeds permitted 24 hour limit. Please try again in a few hours.");
        require(_tokenClaimed.add(_numOfToken) <= _tokenBurnedOnLinkedChain, "MorpherBridge: Token amount exceeds token deleted on linked chain.");
        _chainTransfer(_address, _tokenClaimed, _numOfToken);
        emit OperatorChainTransfer(_address, _numOfToken, _sidechainTransactionHash);
    }
    
    // ------------------------------------------------------------------------
    // trustlessTransferFromSideChain(uint256 _numOfToken, uint256 _claimLimit, bytes32[] memory _proof)
    // Performs a merkle proof on the number of token that have been burned by the user on the side chain.
    // If the number of token claimed on the main chain is less than the number of burned token on the side chain
    // the difference (or less) can be claimed on the main chain.
    // ------------------------------------------------------------------------
    function trustlessTransferFromLinkedChain(uint256 _numOfToken, uint256 _claimLimit, bytes32[] memory _proof) public {
        bytes32 leaf = keccak256(abi.encodePacked(msg.sender, _claimLimit));
        uint256 _tokenClaimed = state.getTokenClaimedOnThisChain(msg.sender);        
        require(mProof(_proof, leaf), "MorpherBridge: Merkle Proof failed. Please make sure you entered the correct claim limit.");
        require(verifyWithdrawOk(_numOfToken), "MorpherBridge: Withdraw amount exceeds permitted 24 hour limit. Please try again in a few hours.");
        require(_tokenClaimed.add(_numOfToken) <= _claimLimit, "MorpherBridge: Token amount exceeds token deleted on linked chain.");     
        _chainTransfer(msg.sender, _tokenClaimed, _numOfToken);   
        emit TrustlessWithdrawFromSideChain(msg.sender, _numOfToken);
    }
    
    // ------------------------------------------------------------------------
    // _chainTransfer(address _address, uint256 _tokenClaimed, uint256 _numOfToken)
    // Creates token on the chain for the user after proving their distruction on the 
    // linked chain has been proven before 
    // ------------------------------------------------------------------------
    function _chainTransfer(address _address, uint256 _tokenClaimed, uint256 _numOfToken) private {
        state.setTokenClaimedOnThisChain(_address, _tokenClaimed.add(_numOfToken));
        state.add24HoursWithdrawn(_numOfToken);
        state.mint(_address, _numOfToken);
    }
        
    // ------------------------------------------------------------------------
    // claimFailedTransferToSidechain(uint256 _wrongSideChainBalance, bytes32[] memory _proof)
    // If token sent to side chain were not credited to the user on the side chain within inactivityPeriod
    // they can reclaim the token on the main chain by submitting the proof that their
    // side chain balance is less than the number of token sent from main chain.
    // ------------------------------------------------------------------------
    function claimFailedTransferToSidechain(uint256 _wrongSideChainBalance, bytes32[] memory _proof) public {
        bytes32 leaf = keccak256(abi.encodePacked(msg.sender, _wrongSideChainBalance));
        uint256 _tokenSentToLinkedChain = getTokenSentToLinkedChain(msg.sender);
        uint256 _tokenSentToLinkedChainTime = getTokenSentToLinkedChainTime(msg.sender);
        uint256 _inactivityPeriod = state.inactivityPeriod();
        
        require(now > _tokenSentToLinkedChainTime.add(_inactivityPeriod), "MorpherBridge: Failed deposits can only be claimed after inactivity period.");
        require(_wrongSideChainBalance < _tokenSentToLinkedChain, "MorpherBridge: Other chain credit is greater equal to wrongSideChainBalance.");
        require(verifyWithdrawOk(_tokenSentToLinkedChain.sub(_wrongSideChainBalance)), "MorpherBridge: Claim amount exceeds permitted 24 hour limit.");
        require(mProof(_proof, leaf), "MorpherBridge: Merkle Proof failed. Enter total amount of deposits on side chain.");
        
        uint256 _claimAmount = _tokenSentToLinkedChain.sub(_wrongSideChainBalance);
        state.setTokenSentToLinkedChain(msg.sender, _tokenSentToLinkedChain.sub(_claimAmount));
        state.add24HoursWithdrawn(_claimAmount);
        state.mint(msg.sender, _claimAmount);
        emit ClaimFailedTransferToSidechain(msg.sender, _claimAmount);
    }

    // ------------------------------------------------------------------------
    // recoverPositionFromSideChain(bytes32[] memory _proof, bytes32 _leaf, bytes32 _marketId, uint256 _timeStamp, uint256 _longShares, uint256 _shortShares, uint256 _meanEntryPrice, uint256 _meanEntrySpread, uint256 _meanEntryLeverage)
    // Failsafe against side chain operator becoming inactive or withholding Times (Time withhold attack).
    // After 72 hours of no update of the side chain merkle root users can withdraw their last recorded
    // positions from side chain to main chain. Overwrites eventually existing position on main chain.
    // ------------------------------------------------------------------------
    function recoverPositionFromSideChain(
        bytes32[] memory _proof,
        bytes32 _leaf,
        bytes32 _marketId,
        uint256 _timeStamp,
        uint256 _longShares,
        uint256 _shortShares,
        uint256 _meanEntryPrice,
        uint256 _meanEntrySpread,
        uint256 _meanEntryLeverage,
        uint256 _liquidationPrice
        ) public sideChainInactive onlyMainchain {
        require(_leaf == state.getPositionHash(msg.sender, _marketId, _timeStamp, _longShares, _shortShares, _meanEntryPrice, _meanEntrySpread, _meanEntryLeverage, _liquidationPrice), "MorpherBridge: leaf does not equal position hash.");
        require(state.getPositionClaimedOnMainChain(_leaf) == false, "MorpherBridge: Position already transferred.");
        require(mProof(_proof,_leaf) == true, "MorpherBridge: Merkle proof failed.");
        state.setPositionClaimedOnMainChain(_leaf);
        state.setPosition(msg.sender, _marketId, _timeStamp, _longShares, _shortShares, _meanEntryPrice, _meanEntrySpread, _meanEntryLeverage, _liquidationPrice);
        emit PositionRecoveryFromSideChain(msg.sender, _leaf);
        // Remark: After resuming operations side chain operator has 72 hours to sync and eliminate transferred positions on side chain to avoid double spend
    }

    // ------------------------------------------------------------------------
    // recoverTokenFromSideChain(bytes32[] memory _proof, bytes32 _leaf, bytes32 _marketId, uint256 _timeStamp, uint256 _longShares, uint256 _shortShares, uint256 _meanEntryPrice, uint256 _meanEntrySpread, uint256 _meanEntryLeverage)
    // Failsafe against side chain operator becoming inactive or withholding times (time withhold attack).
    // After 72 hours of no update of the side chain merkle root users can withdraw their last recorded
    // token balance from side chain to main chain.
    // ------------------------------------------------------------------------
    function recoverTokenFromSideChain(bytes32[] memory _proof, bytes32 _leaf, uint256 _balance) public sideChainInactive onlyMainchain {
        // Require side chain root hash not set on Mainchain for more than 72 hours (=3 days)
        require(_leaf == state.getBalanceHash(msg.sender, _balance), "MorpherBridge: Wrong balance.");
        require(state.getPositionClaimedOnMainChain(_leaf) == false, "MorpherBridge: Token already transferred.");
        require(mProof(_proof,_leaf) == true, "MorpherBridge: Merkle proof failed.");
        require(verifyWithdrawOk(_balance), "MorpherBridge: Withdraw amount exceeds permitted 24 hour limit.");
        state.setPositionClaimedOnMainChain(_leaf);
        _chainTransfer(msg.sender, state.getTokenClaimedOnThisChain(msg.sender), _balance);
        emit TokenRecoveryFromSideChain(msg.sender, _leaf);
        // Remark: Side chain operator must adjust side chain balances for token recoveries before restarting operations to avoid double spend
    }

    // ------------------------------------------------------------------------
    // mProof(bytes32[] memory _proof, bytes32 _leaf)
    // Computes merkle proof against the root hash of the sidechain stored in Morpher state
    // ------------------------------------------------------------------------
    function mProof(bytes32[] memory _proof, bytes32 _leaf) public view returns(bool _isTrue) {
        return MerkleProof.verify(_proof, state.getSideChainMerkleRoot(), _leaf);
    }
}

File 9 of 15: MorpherEscrow.sol
pragma solidity 0.5.16;

import "./Ownable.sol";
import "./SafeMath.sol";
import "./IERC20.sol";

// ----------------------------------------------------------------------------------
// Escrow contract to safely store and release the token allocated to Morpher at
// protocol inception
// ----------------------------------------------------------------------------------

contract MorpherEscrow is Ownable{
    using SafeMath for uint256;

    uint256 public lastEscrowTransferTime;
    address public recipient;
    address public morpherToken;

    uint256 public constant RELEASEAMOUNT = 10**25;
    uint256 public constant RELEASEPERIOD = 30 days;

    event EscrowReleased(uint256 _released, uint256 _leftInEscrow);

    constructor(address _recipientAddress, address _morpherToken, address _coldStorageOwnerAddress) public {
        setRecipientAddress(_recipientAddress);
        setMorpherTokenAddress(_morpherToken);
        lastEscrowTransferTime = now;
        transferOwnership(_coldStorageOwnerAddress);
    }

    // ----------------------------------------------------------------------------------
    // Owner can modify recipient address and update morpherToken adddress
    // ----------------------------------------------------------------------------------
    function setRecipientAddress(address _recipientAddress) public onlyOwner {
        recipient = _recipientAddress;
    }

    function setMorpherTokenAddress(address _address) public onlyOwner {
        morpherToken = _address;
    }

    // ----------------------------------------------------------------------------------
    // Anyone can release funds from escrow if enough time has elapsed
    // Every 30 days 1% of the total initial supply or 10m token are released to Morpher
    // ----------------------------------------------------------------------------------
    function releaseFromEscrow() public {
        require(IERC20(morpherToken).balanceOf(address(this)) > 0, "No funds left in escrow.");
        uint256 _releasedAmount;
        if (now > lastEscrowTransferTime.add(RELEASEPERIOD)) {
            if (IERC20(morpherToken).balanceOf(address(this)) > RELEASEAMOUNT) {
                _releasedAmount = RELEASEAMOUNT;
            } else {
                _releasedAmount = IERC20(morpherToken).balanceOf(address(this));
            }
            IERC20(morpherToken).transfer(recipient, _releasedAmount);
            lastEscrowTransferTime = lastEscrowTransferTime.add(RELEASEPERIOD);
            emit EscrowReleased(_releasedAmount, IERC20(morpherToken).balanceOf(address(this)));
        }
    }
}

File 10 of 15: MorpherGovernance.sol
pragma solidity 0.5.16;
// ------------------------------------------------------------------------
// Morpher Governance (MAIN CHAIN ONLY)
//
// Every user able and willig to lock up sufficient token can become a validator
// of the Morpher protocol. Validators function similiar to a board of directors
// and vote on the protocol Administrator and the Oracle contract.
// The Administrator (=Protocol CEO) has the power to add/delete markets and to
// pause the contracts to allow for updates.
// The Oracle contract is the address of the contract allowed to fetch prices
// from outside the smart contract.
//
// It becomes progressively harder to become a valdiator. Each new validator
// has to lock up (numberOfValidators + 1) * 10m Morpher token. Upon stepping
// down as validator only 99% of the locked up token are returned, the other 1%
// are burned.
//
// Governance is expected to become more sophisticated in the future
// ------------------------------------------------------------------------

import "./Ownable.sol";
import "./SafeMath.sol";
import "./MorpherState.sol";

contract MorpherGovernance is Ownable {

    using SafeMath for uint256;
    MorpherState state;
    
    event BecomeValidator(address indexed _sender, uint256 indexed _myValidatorIndex);
    event StepDownAsValidator(address indexed _sender, uint256 indexed _myValidatorIndex);
    event ElectedAdministrator(address indexed _administratorAddress, uint256 _votes);
    event ElectedOracle(address indexed _oracleAddress, uint256 _votes);

    uint256 public constant MINVALIDATORLOCKUP = 10**25;
    uint256 public constant MAXVALIDATORS = 21;
    uint256 public constant VALIDATORWARMUPPERIOD = 7 days;

    uint256 public numberOfValidators;
    uint256 public lastValidatorJoined;
    uint256 public rewardBasisPoints;

    address public morpherToken;

    mapping(address => uint256) private validatorIndex;
    mapping(address => uint256) private validatorJoinedAtTime;
    mapping(uint256 => address) private validatorAddress;
    mapping(address => address) private oracleVote;
    mapping(address => address) private administratorVote;
    mapping(address => uint256) private countVotes;

    constructor(address _stateAddress, address _coldStorageOwnerAddress) public {
        setMorpherState(_stateAddress);
        transferOwnership(_coldStorageOwnerAddress);        
    }
    
    modifier onlyValidator() {
        require(isValidator(msg.sender), "MorpherGovernance: Only Validators can invoke that function.");
        _;
    }

    function setMorpherState(address _stateAddress) private {
        state = MorpherState(_stateAddress);
    }

    function setMorpherTokenAddress(address _address) public onlyOwner {
        morpherToken = _address;
    }

    function getValidatorAddress(uint256 _index) public view returns (address _address) {
        return validatorAddress[_index];
    }

    function getValidatorIndex(address _address) public view returns (uint256 _index) {
        return validatorIndex[_address];
    }

    function isValidator(address _address) public view returns (bool) {
        return validatorIndex[_address] > 0;
    }

    function setOracle(address  _oracleAddress) private {
        state.setOracleContract(_oracleAddress);
    }

    function setAdministrator(address _administratorAddress) private {
        state.setAdministrator(_administratorAddress);
    }

    function getMorpherAdministrator() public view returns (address _address) {
        return state.getAdministrator();
    }

    function getMorpherOracle() public view returns (address _address)  {
        return state.getOracleContract();
    }

    function getOracleVote(address _address) public view returns (address _votedOracleAddress) {
        return oracleVote[_address];
    }

    function becomeValidator() public {
        // To become a validator you have to lock up 10m * (number of validators + 1) Morpher Token in escrow
        // After a warmup period of 7 days the new validator can vote on Oracle contract and protocol Administrator
        uint256 _requiredAmount = MINVALIDATORLOCKUP.mul(numberOfValidators.add(1));
        require(state.balanceOf(msg.sender) >= _requiredAmount, "MorpherGovernance: Insufficient balance to become Validator.");
        require(isValidator(msg.sender) == false, "MorpherGovernance: Address is already Validator.");
        require(numberOfValidators <= MAXVALIDATORS, "MorpherGovernance: number of Validators can not exceed Max Validators.");
        state.transfer(msg.sender, address(this), _requiredAmount);
        numberOfValidators = numberOfValidators.add(1);
        validatorIndex[msg.sender] = numberOfValidators;
        validatorJoinedAtTime[msg.sender] = now;
        lastValidatorJoined = now;
        validatorAddress[numberOfValidators] = msg.sender;
        emit BecomeValidator(msg.sender, numberOfValidators);
    }

    function stepDownValidator() public onlyValidator {
        // Stepping down as validator nullifies the validator's votes and releases his token
        // from escrow. If the validator stepping down is not the validator that joined last,
        // all validators who joined after the validator stepping down receive 10^7 * 0.99 token from
        // escrow, and their validator ordinal number is reduced by one. E.g. if validator 3 of 5 steps down
        // validator 4 becomes validator 3, and validator 5 becomes validator 4. Both receive 10^7 * 0.99 token
        // from escrow, as their new position requires fewer token in lockup. 1% of the token released from escrow 
        // are burned for every validator receiving a payout. 
        // Burning prevents vote delay attacks: validators stepping down and re-joining could
        // delay votes for VALIDATORWARMUPPERIOD.
        uint256 _myValidatorIndex = validatorIndex[msg.sender];
        require(state.balanceOf(address(this)) >= MINVALIDATORLOCKUP.mul(numberOfValidators), "MorpherGovernance: Escrow does not have enough funds. Should not happen.");
        // Stepping down as validator potentially releases token to the other validatorAddresses
        for (uint256 i = _myValidatorIndex; i < numberOfValidators; i++) {
            validatorAddress[i] = validatorAddress[i+1];
            validatorIndex[validatorAddress[i]] = i;
            // Release 9.9m of token to every validator moving up, burn 0.1m token
            state.transfer(address(this), validatorAddress[i], MINVALIDATORLOCKUP.div(100).mul(99));
            state.burn(address(this), MINVALIDATORLOCKUP.div(100));
        }
        // Release 99% of escrow token of validator dropping out, burn 1%
        validatorAddress[numberOfValidators] = address(0);
        validatorIndex[msg.sender] = 0;
        validatorJoinedAtTime[msg.sender] = 0;
        oracleVote[msg.sender] = address(0);
        administratorVote[msg.sender] = address(0);
        numberOfValidators = numberOfValidators.sub(1);
        countOracleVote();
        countAdministratorVote();
        state.transfer(address(this), msg.sender, MINVALIDATORLOCKUP.mul(_myValidatorIndex).div(100).mul(99));
        state.burn(address(this), MINVALIDATORLOCKUP.mul(_myValidatorIndex).div(100));
        emit StepDownAsValidator(msg.sender, validatorIndex[msg.sender]);
    }

    function voteOracle(address _oracleAddress) public onlyValidator {
        require(validatorJoinedAtTime[msg.sender].add(VALIDATORWARMUPPERIOD) < now, "MorpherGovernance: Validator was just appointed and is not eligible to vote yet.");
        require(lastValidatorJoined.add(VALIDATORWARMUPPERIOD) < now, "MorpherGovernance: New validator joined the board recently, please wait for the end of the warm up period.");
        oracleVote[msg.sender] = _oracleAddress;
        // Count Oracle Votes
        (address _votedOracleAddress, uint256 _votes) = countOracleVote();
        emit ElectedOracle(_votedOracleAddress, _votes);
    }

    function voteAdministrator(address _administratorAddress) public onlyValidator {
        require(validatorJoinedAtTime[msg.sender].add(VALIDATORWARMUPPERIOD) < now, "MorpherGovernance: Validator was just appointed and is not eligible to vote yet.");
        require(lastValidatorJoined.add(VALIDATORWARMUPPERIOD) < now, "MorpherGovernance: New validator joined the board recently, please wait for the end of the warm up period.");
        administratorVote[msg.sender] = _administratorAddress;
        // Count Administrator Votes
        (address _appointedAdministrator, uint256 _votes) = countAdministratorVote();
        emit ElectedAdministrator(_appointedAdministrator, _votes);
    }

    function countOracleVote() public returns (address _votedOracleAddress, uint256 _votes) {
        // Count oracle votes
        for (uint256 i = 1; i <= numberOfValidators; i++) {
            countVotes[oracleVote[validatorAddress[i]]]++;
            if (countVotes[oracleVote[validatorAddress[i]]] > _votes) {
                _votes = countVotes[oracleVote[validatorAddress[i]]];
                _votedOracleAddress = oracleVote[validatorAddress[i]];
            }
        }
        // Evaluate: Simple majority of Validators resets oracleAddress
        if (_votes > numberOfValidators.div(2)) {
            setOracle(_votedOracleAddress);
        }
        for (uint256 i = 1; i <= numberOfValidators; i++) {
            countVotes[administratorVote[validatorAddress[i]]] = 0;
        }
        return(_votedOracleAddress, _votes);
    }

    function countAdministratorVote() public returns (address _appointedAdministrator, uint256 _votes) {
        // Count Administrator votes
        for (uint256 i=1; i<=numberOfValidators; i++) {
            countVotes[administratorVote[validatorAddress[i]]]++;
            if (countVotes[administratorVote[validatorAddress[i]]] > _votes) {
                _votes = countVotes[administratorVote[validatorAddress[i]]];
                _appointedAdministrator = administratorVote[validatorAddress[i]];
            }
        }
        // Evaluate: Simple majority of Validators resets administratorAddress
        if (_votes > numberOfValidators / 2) {
            setAdministrator(_appointedAdministrator);
        }
        for (uint256 i = 1; i <= numberOfValidators; i++) {
            countVotes[administratorVote[validatorAddress[i]]] = 0;
        }
        return(_appointedAdministrator, _votes);
    }
}

File 11 of 15: MorpherOracle.sol
pragma solidity 0.5.16;

import "./Ownable.sol";
import "./MorpherTradeEngine.sol";

// ----------------------------------------------------------------------------------
// Morpher Oracle contract
// The oracle initates a new trade by calling trade engine and requesting a new orderId.
// An event is fired by the contract notifying the oracle operator to query a price/liquidation unchecked
// for a market/user and return the information via the callback function. Since calling
// the callback function requires gas, the user must send a fixed amount of Ether when
// creating their order.
// ----------------------------------------------------------------------------------

contract MorpherOracle is Ownable {

    MorpherTradeEngine tradeEngine;

    bool public paused;

    uint256 public gasForCallback;
    address payable public callBackCollectionAddress;

    mapping(address => bool) public callBackAddress;

// ----------------------------------------------------------------------------------
// Events
// ----------------------------------------------------------------------------------
    event OrderCreated(
        bytes32 indexed _orderId,
        address indexed _address,
        bytes32 indexed _marketId,
        bool _tradeAmountGivenInShares,
        uint256 _tradeAmount,
        bool _tradeDirection,
        uint256 _orderLeverage
        );

    event LiquidationOrderCreated(
        bytes32 indexed _orderId,
        address _sender,
        address indexed _address,
        bytes32 indexed _marketId
        );

    event OrderProcessed(
        bytes32 indexed _orderId,
        uint256 _price,
        uint256 _spread,
        uint256 _positionLiquidationTimestamp,
        uint256 _timeStamp,
        uint256 _newLongShares,
        uint256 _newShortShares,
        uint256 _newMeanEntry,
        uint256 _newMeanSprad,
        uint256 _newMeanLeverage,
        uint256 _liquidationPrice
        );

    event OrderFailed(
        bytes32 indexed _orderId,
        address indexed _address,
        bytes32 indexed _marketId,
        bool _tradeAmountGivenInShares,
        uint256 _tradeAmount,
        bool _tradeDirection,
        uint256 _orderLeverage
        );

    event OrderCancelled(
        bytes32 indexed _orderId,
        address indexed _sender
        );

    event CallbackAddressEnabled(
        address indexed _address
        );

    event CallbackAddressDisabled(
        address indexed _address
        );

    event OraclePaused(
        bool _paused
        );

    event CallBackCollectionAddressChange(
        address _address
        );

    event SetGasForCallback(
        uint256 _gasForCallback
        );

    event LinkTradeEngine(
        address _address
        );

    modifier onlyOracleOperator {
        require(isCallbackAddress(msg.sender), "MorpherOracle: Only the oracle operator can call this function.");
        _;
    }

    modifier notPaused {
        require(paused == false, "MorpherOracle: Oracle paused, aborting");
        _;
    }

   constructor(address _tradeEngineAddress, address _callBackAddress, address payable _gasCollectionAddress, uint256 _gasForCallback, address _coldStorageOwnerAddress) public {
        setTradeEngineAddress(_tradeEngineAddress);
        enableCallbackAddress(_callBackAddress);
        setCallbackCollectionAddress(_gasCollectionAddress);
        setGasForCallback(_gasForCallback);
        transferOwnership(_coldStorageOwnerAddress);
    }

// ----------------------------------------------------------------------------------
// Setter/getter functions for trade engine address, oracle operator (callback) address,
// and prepaid gas limit for callback function
// ----------------------------------------------------------------------------------
    function setTradeEngineAddress(address _address) public onlyOwner {
        tradeEngine = MorpherTradeEngine(_address);
        emit LinkTradeEngine(_address);
    }

    function setGasForCallback(uint256 _gasForCallback) public onlyOwner {
        gasForCallback = _gasForCallback;
        emit SetGasForCallback(_gasForCallback);
    }

    function enableCallbackAddress(address _address) public onlyOwner {
        callBackAddress[_address] = true;
        emit CallbackAddressEnabled(_address);
    }

    function disableCallbackAddress(address _address) public onlyOwner {
        callBackAddress[_address] = false;
        emit CallbackAddressDisabled(_address);
    }

    function isCallbackAddress(address _address) public view returns (bool _isCallBackAddress) {
        return callBackAddress[_address];
    }

    function setCallbackCollectionAddress(address payable _address) public onlyOwner {
        callBackCollectionAddress = _address;
        emit CallBackCollectionAddressChange(_address);
    }

// ----------------------------------------------------------------------------------
// emitOrderFailed
// Can be called by Oracle Operator to notifiy user of failed order
// ----------------------------------------------------------------------------------
    function emitOrderFailed(
        bytes32 _orderId,
        address _address,
        bytes32 _marketId,
        bool _tradeAmountGivenInShares,
        uint256 _tradeAmount,
        bool _tradeDirection,
        uint256 _orderLeverage
    ) public onlyOracleOperator {
        emit OrderFailed(
            _orderId,
            _address,
            _marketId,
            _tradeAmountGivenInShares,
            _tradeAmount,
            _tradeDirection,
            _orderLeverage);
    }

// ----------------------------------------------------------------------------------
// createOrder(bytes32  _marketId, bool _tradeAmountGivenInShares, uint256 _tradeAmount, bool _tradeDirection, uint256 _orderLeverage)
// Request a new orderId from trade engine and fires event for price/liquidation check request.
// ----------------------------------------------------------------------------------
    function createOrder(
        bytes32 _marketId,
        bool _tradeAmountGivenInShares,
        uint256 _tradeAmount,
        bool _tradeDirection,
        uint256 _orderLeverage
        ) public payable notPaused returns (bytes32 _orderId) {
        if (gasForCallback > 0) {
            require(msg.value >= gasForCallback, "MorpherOracle: Must transfer gas costs for Oracle Callback function.");
            callBackCollectionAddress.transfer(msg.value);
        }
        _orderId = tradeEngine.requestOrderId(msg.sender, _marketId, _tradeAmountGivenInShares, _tradeAmount, _tradeDirection, _orderLeverage);
        emit OrderCreated(
            _orderId,
            msg.sender,
            _marketId,
            _tradeAmountGivenInShares,
            _tradeAmount,
            _tradeDirection,
            _orderLeverage
            );
        return _orderId;
    }

// ----------------------------------------------------------------------------------
// cancelOrder(bytes32  _orderId)
// Users can cancel their own orders before the _callback has been executed
// ----------------------------------------------------------------------------------
    function cancelOrder(bytes32 _orderId) public {
        tradeEngine.cancelOrder(_orderId, msg.sender);
        emit OrderCancelled(
            _orderId,
            msg.sender
            );
    }

// ----------------------------------------------------------------------------------
// Setter/getter functions for pausing the Oracle contract
// ----------------------------------------------------------------------------------
    function pauseOracle() public onlyOwner {
        paused = true;
        emit OraclePaused(true);
    }

    function unpauseOracle() public onlyOwner {
        paused = false;
        emit OraclePaused(false);
    }

// ----------------------------------------------------------------------------------
// createLiquidationOrder(address _address, bytes32 _marketId)
// Checks if position has been liquidated since last check. Requires gas for callback
// function. Anyone can issue a liquidation order for any other address and market.
// ----------------------------------------------------------------------------------
    function createLiquidationOrder(
        address _address,
        bytes32 _marketId
        ) public notPaused payable returns (bytes32 _orderId) {
        if (gasForCallback > 0) {
            require(msg.value >= gasForCallback, "MorpherOracle: Must transfer gas costs for Oracle Callback function.");
            callBackCollectionAddress.transfer(msg.value);
        }
        _orderId = tradeEngine.requestOrderId(_address, _marketId, true, 0, true, 10**8);
        emit LiquidationOrderCreated(_orderId, msg.sender, _address, _marketId);
        return _orderId;
    }

// ----------------------------------------------------------------------------------
// __callback(bytes32 _orderId, uint256 _price, uint256 _spread, uint256 _liquidationTimestamp, uint256 _timeStamp)
// Called by the oracle operator. Writes price/spread/liquidiation check to the blockchain.
// Trade engine processes the order and updates the portfolio in state if successful.
// ----------------------------------------------------------------------------------
    function __callback(
        bytes32 _orderId,
        uint256 _price,
        uint256 _spread,
        uint256 _liquidationTimestamp,
        uint256 _timeStamp
        ) public onlyOracleOperator notPaused returns (uint256 _newLongShares, uint256 _newShortShares, uint256 _newMeanEntry, uint256 _newMeanSpread, uint256 _newMeanLeverage, uint256 _liquidationPrice)  {
        (
            _newLongShares,
            _newShortShares,
            _newMeanEntry,
            _newMeanSpread,
            _newMeanLeverage,
            _liquidationPrice
        ) = tradeEngine.processOrder(_orderId, _price, _spread, _liquidationTimestamp, _timeStamp);
        emit OrderProcessed(
            _orderId,
            _price,
            _spread,
            _liquidationTimestamp,
            _timeStamp,
            _newLongShares,
            _newShortShares,
            _newMeanEntry,
            _newMeanSpread,
            _newMeanLeverage,
            _liquidationPrice
            );
        return (_newLongShares, _newShortShares, _newMeanEntry, _newMeanSpread, _newMeanLeverage, _liquidationPrice);
    }

// ----------------------------------------------------------------------------------
// Auxiliary function to hash a string market name i.e.
// "CRYPTO_BTC" => 0x0bc89e95f9fdaab7e8a11719155f2fd638cb0f665623f3d12aab71d1a125daf9;
// ----------------------------------------------------------------------------------
    function stringToHash(string memory _source) public pure returns (bytes32 _result) {
        return keccak256(abi.encodePacked(_source));
    }
}

File 12 of 15: MorpherToken.sol
pragma solidity 0.5.16;

import "./IERC20.sol";
import "./Ownable.sol";
import "./SafeMath.sol";
import "./MorpherState.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20Mintable}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract MorpherToken is IERC20, Ownable {

    MorpherState state;
    using SafeMath for uint256;

    string public constant name     = "Morpher";
    string public constant symbol   = "MPH";
    uint8  public constant decimals = 18;
    
    modifier onlyState {
        require(msg.sender == address(state), "ERC20: caller must be MorpherState contract.");
        _;
    }

    modifier canTransfer {
        require(state.mainChain() == true || state.getCanTransfer(msg.sender), "ERC20: token transfers disabled on sidechain.");
        _;
    }
    
    event LinkState(address _address);

    // ------------------------------------------------------------------------
    // Constructor
    // ------------------------------------------------------------------------
    constructor(address _stateAddress, address _coldStorageOwnerAddress) public {
        setMorpherState(_stateAddress);
        transferOwnership(_coldStorageOwnerAddress);
    }

    // ------------------------------------------------------------------------
    // Links Token Contract with State
    // ------------------------------------------------------------------------
    function setMorpherState(address _stateAddress) public onlyOwner {
        state = MorpherState(_stateAddress);
        emit LinkState(_stateAddress);
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view returns (uint256) {
        return state.totalSupply();
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address _account) public view returns (uint256) {
        return state.balanceOf(_account);
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     * 
     * Emits a {Transfer} event via emitTransfer called by MorpherState
     */
    function transfer(address _recipient, uint256 _amount) public returns (bool) {
        _transfer(msg.sender, _recipient, _amount);
        return true;
    }

   /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address _owner, address _spender) public view returns (uint256) {
        return state.getAllowance(_owner, _spender);
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address _spender, uint256 _amount) public returns (bool) {
        _approve(msg.sender, _spender, _amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20};
     *
     * Requirements:
     * - `_sender` and `_recipient` cannot be the zero address.
     * - `_sender` must have a balance of at least `amount`.
     * - the caller must have allowance for `_sender`'s tokens of at least
     * `amount`.
     */
    function transferFrom(address _sender, address _recipient, uint256 amount) public returns (bool) {
        _transfer(_sender, _recipient, amount);
        _approve(_sender, msg.sender, state.getAllowance(_sender, msg.sender).sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `_spender` cannot be the zero address.
     */
    function increaseAllowance(address _spender, uint256 _addedValue) public returns (bool) {
        _approve(msg.sender, _spender, state.getAllowance(msg.sender, _spender).add(_addedValue));
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address _spender, uint256 _subtractedValue) public returns (bool) {
        _approve(msg.sender, _spender,  state.getAllowance(msg.sender, _spender).sub(_subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }

    /**
     * @dev Caller destroys `_amount` tokens permanently
     *
     * Emits a {Transfer} event to zero address called by MorpherState via emitTransfer.
     *
     * Requirements:
     *
     * - Caller must have token balance of at least `_amount`
     * 
     */
     function burn(uint256 _amount) public returns (bool) {
        state.burn(msg.sender, _amount);
        return true;
    }

    /**
     * @dev Emits a {Transfer} event
     *
     * MorpherState emits a {Transfer} event.
     *
     * Requirements:
     *
     * - Caller must be MorpherState
     * 
     */
     function emitTransfer(address _from, address _to, uint256 _amount) public onlyState {
        emit Transfer(_from, _to, _amount);
    }

     /**
     * @dev Moves tokens `_amount` from `sender` to `_recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event via emitTransfer called by MorpherState
     *
     * Requirements:
     *
     * - `_sender` cannot be the zero address.
     * - `_recipient` cannot be the zero address.
     * - `_sender` must have a balance of at least `_amount`.
     */
    function _transfer(address _sender, address _recipient, uint256 _amount) canTransfer internal {
        require(_sender != address(0), "ERC20: transfer from the zero address");
        require(_recipient != address(0), "ERC20: transfer to the zero address");
        require(state.balanceOf(_sender) >= _amount, "ERC20: transfer amount exceeds balance");
        state.transfer(_sender, _recipient, _amount);
    }

    /**
     * @dev Sets `_amount` as the allowance of `spender` over the `owner`s tokens.
     *
     * This is internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address _owner, address _spender, uint256 _amount) internal {
        require(_owner != address(0), "ERC20: approve from the zero address");
        require(_spender != address(0), "ERC20: approve to the zero address");
        state.setAllowance(_owner, _spender, _amount);
        emit Approval(_owner, _spender, _amount);
    }

    // ------------------------------------------------------------------------
    // Don't accept ETH
    // ------------------------------------------------------------------------
    function () external payable {
        revert("ERC20: You can't deposit Ether here");
    }
}

File 13 of 15: MorpherTradeEngine.sol
pragma solidity 0.5.16;

import "./Ownable.sol";
import "./SafeMath.sol";
import "./MorpherState.sol";

// ----------------------------------------------------------------------------------
// Tradeengine of the Morpher platform
// Creates and processes orders, and computes the state change of portfolio.
// Needs writing/reading access to/from Morpher State. Order objects are stored locally,
// portfolios are stored in state.
// ----------------------------------------------------------------------------------

contract MorpherTradeEngine is Ownable {
    MorpherState state;
    using SafeMath for uint256;

// ----------------------------------------------------------------------------
// Precision of prices and leverage
// ----------------------------------------------------------------------------
    uint256 constant PRECISION = 10**8;
    uint256 public orderNonce;
    bytes32 public lastOrderId;

// ----------------------------------------------------------------------------
// Order struct contains all order specific varibles. Variables are completed
// during processing of trade. State changes are saved in the order struct as
// well, since local variables would lead to stack to deep errors *sigh*.
// ----------------------------------------------------------------------------
    struct order {
        address userId;
        bool tradeAmountGivenInShares;
        bytes32 marketId;
        uint256 tradeAmount;
        bool tradeDirection; // true = long, false = short
        uint256 liquidationTimestamp;
        uint256 marketPrice;
        uint256 marketSpread;
        uint256 orderLeverage;
        uint256 timeStamp;
        uint256 longSharesOrder;
        uint256 shortSharesOrder;
        uint256 balanceDown;
        uint256 balanceUp;
        uint256 newLongShares;
        uint256 newShortShares;
        uint256 newMeanEntryPrice;
        uint256 newMeanEntrySpread;
        uint256 newMeanEntryLeverage;
        uint256 newLiquidationPrice;
    }

    mapping(bytes32 => order) private orders;

// ----------------------------------------------------------------------------
// Events
// Order created/processed events are fired by MorpherOracle.
// ----------------------------------------------------------------------------

    event PositionLiquidated(
        address indexed _address,
        bytes32 indexed _marketId,
        bool _longPosition,
        uint256 _timeStamp,
        uint256 _marketPrice,
        uint256 _marketSpread
    );

    event OrderCancelled(
        bytes32 indexed _orderId,
        address indexed _address
    );

    event OrderIdRequested(
        bytes32 _orderId,
        address indexed _address,
        bytes32 indexed _marketId,
        bool _tradeAmountGivenInShares,
        uint256 _tradeAmount,
        bool _tradeDirection,
        uint256 _orderLeverage
    );

    event OrderProcessed(
        bytes32 _orderId,
        uint256 _marketPrice,
        uint256 _marketSpread,
        uint256 _liquidationTimestamp,
        uint256 _timeStamp,
        uint256 _newLongShares,
        uint256 _newShortShares,
        uint256 _newAverageEntry,
        uint256 _newAverageSpread,
        uint256 _newAverageLeverage,
        uint256 _liquidationPrice
    );

    event PositionUpdated(
        address _userId,
        bytes32 _marketId,
        uint256 _timeStamp,
        uint256 _newLongShares,
        uint256 _newShortShares,
        uint256 _newMeanEntryPrice,
        uint256 _newMeanEntrySpread,
        uint256 _newMeanEntryLeverage,
        uint256 _newLiquidationPrice,
        uint256 _mint,
        uint256 _burn
    );

    event LinkState(address _address);

    constructor(address _stateAddress, address _coldStorageOwnerAddress) public {
        setMorpherState(_stateAddress);
        transferOwnership(_coldStorageOwnerAddress);
    }

    modifier onlyOracle {
        require(msg.sender == state.getOracleContract(), "MorpherTradeEngine: function can only be called by Oracle Contract.");
        _;
    }

    modifier onlyAdministrator {
        require(msg.sender == getAdministrator(), "MorpherTradeEngine: function can only be called by the Administrator.");
        _;
    }

// ----------------------------------------------------------------------------
// Administrative functions
// Set state address, get administrator address
// ----------------------------------------------------------------------------

    function setMorpherState(address _stateAddress) public onlyOwner {
        state = MorpherState(_stateAddress);
        emit LinkState(_stateAddress);
    }

    function getAdministrator() public view returns(address _administrator) {
        return state.getAdministrator();
    }

// ----------------------------------------------------------------------------
// requestOrderId(address _address, bytes32 _marketId, bool _tradeAmountGivenInShares, uint256 _tradeAmount, bool _tradeDirection, uint256 _orderLeverage)
// Creates a new order object with unique orderId and assigns order information.
// Must be called by MorpherOracle contract.
// ----------------------------------------------------------------------------

    function requestOrderId(
        address _address,
        bytes32 _marketId,
        bool _tradeAmountGivenInShares,
        uint256 _tradeAmount,
        bool _tradeDirection,
        uint256 _orderLeverage
        ) public onlyOracle returns (bytes32 _orderId) {
        require(_orderLeverage >= PRECISION, "MorpherTradeEngine: leverage too small. Leverage precision is 1e8");
        require(_orderLeverage <= state.getMaximumLeverage(), "MorpherTradeEngine: leverage exceeds maximum allowed leverage.");
        require(state.getMarketActive(_marketId) == true, "MorpherTradeEngine: market unknown or currently not enabled for trading.");
        require(state.getNumberOfRequests(_address) <= state.getNumberOfRequestsLimit() ||
            state.getLastRequestBlock(_address) < block.number,
            "MorpherTradeEngine: request exceeded maximum permitted requests per block."
        );
        state.setLastRequestBlock(_address);
        state.increaseNumberOfRequests(_address);
        orderNonce++;
        _orderId = keccak256(
            abi.encodePacked(
                _address,
                block.number,
                _marketId,
                _tradeAmountGivenInShares,
                _tradeAmount,
                _tradeDirection,
                _orderLeverage,
                orderNonce
                )
            );
        lastOrderId = _orderId;
        orders[_orderId].userId = _address;
        orders[_orderId].marketId = _marketId;
        orders[_orderId].tradeAmountGivenInShares = _tradeAmountGivenInShares;
        orders[_orderId].tradeAmount = _tradeAmount;
        orders[_orderId].tradeDirection = _tradeDirection;
        orders[_orderId].orderLeverage = _orderLeverage;
        emit OrderIdRequested(
            _orderId,
            _address,
            _marketId,
            _tradeAmountGivenInShares,
            _tradeAmount,
            _tradeDirection,
            _orderLeverage
        );
        return _orderId;
    }

// ----------------------------------------------------------------------------
// Getter functions for orders, shares, and positions
// ----------------------------------------------------------------------------

    function getOrder(bytes32 _orderId) public view returns (
        address _userId,
        bytes32 _marketId,
        uint256 _tradeAmount,
        uint256 _marketPrice,
        uint256 _marketSpread,
        uint256 _orderLeverage
        ) {
        return(
            orders[_orderId].userId,
            orders[_orderId].marketId,
            orders[_orderId].tradeAmount,
            orders[_orderId].marketPrice,
            orders[_orderId].marketSpread,
            orders[_orderId].orderLeverage
            );
    }

    function getOrderShares(bytes32 _orderId) public view returns (
        uint256 _longSharesOrder,
        uint256 _shortSharesOrder,
        uint256 _tradeAmount,
        bool _tradeDirection,
        uint256 _balanceUp,
        uint256 _balanceDown) {
        return(
            orders[_orderId].longSharesOrder,
            orders[_orderId].shortSharesOrder,
            orders[_orderId].tradeAmount,
            orders[_orderId].tradeDirection,
            orders[_orderId].balanceUp,
            orders[_orderId].balanceDown
        );
    }

    function getPosition(address _address, bytes32 _marketId) public view returns (
        uint256 _positionLongShares,
        uint256 _positionShortShares,
        uint256 _positionAveragePrice,
        uint256 _positionAverageSpread,
        uint256 _positionAverageLeverage,
        uint256 _liquidationPrice
        ) {
        return(
            state.getLongShares(_address, _marketId),
            state.getShortShares(_address, _marketId),
            state.getMeanEntryPrice(_address,_marketId),
            state.getMeanEntrySpread(_address,_marketId),
            state.getMeanEntryLeverage(_address,_marketId),
            state.getLiquidationPrice(_address,_marketId)
        );
    }

// ----------------------------------------------------------------------------
// liquidate(bytes32 _orderId)
// Checks for bankruptcy of position between its last update and now
// Time check is necessary to avoid two consecutive / unorderded liquidations
// ----------------------------------------------------------------------------

    function liquidate(bytes32 _orderId) private {
        address _address = orders[_orderId].userId;
        bytes32 _marketId = orders[_orderId].marketId;
        uint256 _liquidationTimestamp = orders[_orderId].liquidationTimestamp;
        if (_liquidationTimestamp > state.getLastUpdated(_address, _marketId)) {
            if (state.getLongShares(_address,_marketId) > 0) {
                state.setPosition(
                    _address,
                    _marketId,
                    orders[_orderId].timeStamp,
                    0,
                    state.getShortShares(_address, _marketId),
                    0,
                    0,
                    PRECISION,
                    0);
                emit PositionLiquidated(
                    _address,
                    _marketId,
                    true,
                    orders[_orderId].timeStamp,
                    orders[_orderId].marketPrice,
                    orders[_orderId].marketSpread
                );
            }
            if (state.getShortShares(_address,_marketId) > 0) {
                state.setPosition(
                    _address,
                    _marketId,
                    orders[_orderId].timeStamp,
                    state.getLongShares(_address, _marketId),
                    0,
                    0,
                    0,
                    PRECISION,
                    0
                );
                emit PositionLiquidated(
                    _address,
                    _marketId,
                    false,
                    orders[_orderId].timeStamp,
                    orders[_orderId].marketPrice,
                    orders[_orderId].marketSpread
                );
            }
        }
    }

// ----------------------------------------------------------------------------
// processOrder(bytes32 _orderId, uint256 _marketPrice, uint256 _marketSpread, uint256 _liquidationTimestamp, uint256 _timeStamp)
// ProcessOrder receives the price/spread/liqidation information from the Oracle and
// triggers the processing of the order. If successful, processOrder updates the portfolio state.
// Liquidation time check is necessary to avoid two consecutive / unorderded liquidations
// ----------------------------------------------------------------------------

    function processOrder(
        bytes32 _orderId,
        uint256 _marketPrice,
        uint256 _marketSpread,
        uint256 _liquidationTimestamp,
        uint256 _timeStamp
        ) public onlyOracle returns (
            uint256 _newLongShares,
            uint256 _newShortShares,
            uint256 _newAverageEntry,
            uint256 _newAverageSpread,
            uint256 _newAverageLeverage,
            uint256 _liquidationPrice
        ) {
        require(orders[_orderId].userId != address(0), "MorpherTradeEngine: unable to process, order has been deleted.");
        require(_marketPrice > 0, "MorpherTradeEngine: market priced at zero. Buy order cannot be processed.");
        require(_marketPrice >= _marketSpread, "MorpherTradeEngine: market price lower then market spread. Order cannot be processed.");
        address _address = orders[_orderId].userId;
        bytes32 _marketId = orders[_orderId].marketId;
        require(state.getMarketActive(_marketId) == true, "MorpherTradeEngine: market unknown or currently not enabled for trading.");
        orders[_orderId].marketPrice = _marketPrice;
        orders[_orderId].marketSpread = _marketSpread;
        orders[_orderId].timeStamp = _timeStamp;
        orders[_orderId].liquidationTimestamp = _liquidationTimestamp;

        // Check if previous position on that market was liquidated
        if (_liquidationTimestamp > state.getLastUpdated(_address, _marketId)) {
            liquidate(_orderId);
        }

		if (orders[_orderId].tradeAmount > 0)  {
            if (orders[_orderId].tradeDirection) {
                processBuyOrder(_orderId);
            } else {
                processSellOrder(_orderId);
		    }
		}	

        delete orders[_orderId];
        emit OrderProcessed(
            _orderId,
            _marketPrice,
            _marketSpread,
            _liquidationTimestamp,
            _timeStamp,
            _newLongShares,
            _newShortShares,
            _newAverageEntry,
            _newAverageSpread,
            _newAverageLeverage,
            _liquidationPrice
        );
        return (
            state.getLongShares(_address, _marketId),
            state.getShortShares(_address, _marketId),
            state.getMeanEntryPrice(_address,_marketId),
            state.getMeanEntrySpread(_address,_marketId),
            state.getMeanEntryLeverage(_address,_marketId),
            state.getLiquidationPrice(_address,_marketId)
        );
    }

// ----------------------------------------------------------------------------
// function cancelOrder(bytes32 _orderId, address _address)
// Users or Administrator can delete pending orders before the callback went through
// ----------------------------------------------------------------------------
    function cancelOrder(bytes32 _orderId, address _address) public onlyOracle {
        require(_address == orders[_orderId].userId || _address == getAdministrator(), "MorpherTradeEngine: only Administrator or user can cancel an order.");
        require(orders[_orderId].userId != address(0), "MorpherTradeEngine: unable to process, order does not exist.");
        delete orders[_orderId];
        emit OrderCancelled(_orderId, _address);
    }

// ----------------------------------------------------------------------------
// shortShareValue / longShareValue compute the value of a virtual future
// given current price/spread/leverage of the market and mean price/spread/leverage
// at the beginning of the trade
// ----------------------------------------------------------------------------
    function shortShareValue(
        uint256 _positionAveragePrice,
        uint256 _positionAverageLeverage,
        uint256 _liquidationPrice,
        uint256 _marketPrice,
        uint256 _marketSpread,
        uint256 _orderLeverage,
        bool _sell
        ) public pure returns (uint256 _shareValue) {

        uint256 _averagePrice = _positionAveragePrice;
        uint256 _averageLeverage = _positionAverageLeverage;

        if (_positionAverageLeverage < PRECISION) {
            // Leverage can never be less than 1. Fail safe for empty positions, i.e. undefined _positionAverageLeverage
            _averageLeverage = PRECISION;
        }
        if (_sell == false) {
            // New short position
            // It costs marketPrice + marketSpread to build up a new short position
            _averagePrice = _marketPrice;
	        // This is the average Leverage
	        _averageLeverage = _orderLeverage;
        }
        if (
            _liquidationPrice <= _marketPrice
            ) {
	        // Position is worthless
            _shareValue = 0;
        } else {
            // The regular share value is 2x the entry price minus the current price for short positions.
            _shareValue = _averagePrice.mul((PRECISION.add(_averageLeverage))).div(PRECISION);
            _shareValue = _shareValue.sub(_marketPrice.mul(_averageLeverage).div(PRECISION));
            if (_sell == true) {
                // We have to reduce the share value by the average spread (i.e. the average expense to build up the position)
                // and reduce the value further by the spread for selling.
                _shareValue = _shareValue.sub(_marketSpread.mul(_averageLeverage).div(PRECISION));
            } else {
                // If a new short position is built up each share costs value + spread
                _shareValue = _shareValue.add(_marketSpread.mul(_orderLeverage).div(PRECISION));
            }
        }
        return _shareValue;
    }

    function longShareValue(
        uint256 _positionAveragePrice,
        uint256 _positionAverageLeverage,
        uint256 _liquidationPrice,
        uint256 _marketPrice,
        uint256 _marketSpread,
        uint256 _orderLeverage,
        bool _sell
        ) public pure returns (uint256 _shareValue) {

        uint256 _averagePrice = _positionAveragePrice;
        uint256 _averageLeverage = _positionAverageLeverage;

        if (_positionAverageLeverage < PRECISION) {
            // Leverage can never be less than 1. Fail safe for empty positions, i.e. undefined _positionAverageLeverage
            _averageLeverage = PRECISION;
        }
        if (_sell == false) {
            // New long position
            // It costs marketPrice + marketSpread to build up a new long position
            _averagePrice = _marketPrice;
	        // This is the average Leverage
	        _averageLeverage = _orderLeverage;
        }
        if (
            _marketPrice <= _liquidationPrice
            ) {
	        // Position is worthless
            _shareValue = 0;
        } else {
            _shareValue = _averagePrice.mul(_averageLeverage.sub(PRECISION)).div(PRECISION);
            // The regular share value is market price times leverage minus entry price times entry leverage minus one.
            _shareValue = (_marketPrice.mul(_averageLeverage).div(PRECISION)).sub(_shareValue);
            if (_sell == true) {
                // We sell a long and have to correct the shareValue with the averageSpread and the currentSpread for selling.
                _shareValue = _shareValue.sub(_marketSpread.mul(_averageLeverage).div(PRECISION));
            } else {
                // We buy a new long position and have to pay the spread
                _shareValue = _shareValue.add(_marketSpread.mul(_orderLeverage).div(PRECISION));
            }
        }
        return _shareValue;
    }

// ----------------------------------------------------------------------------
// processBuyOrder(bytes32 _orderId)
// Converts orders specified in virtual shares to orders specified in Morpher token
// and computes the number of short shares that are sold and long shares that are bought.
// long shares are bought only if the order amount exceeds all open short positions
// ----------------------------------------------------------------------------

    function processBuyOrder(bytes32 _orderId) private {
        if (orders[_orderId].tradeAmountGivenInShares == false) {
            // Investment was specified in units of MPH
            if (orders[_orderId].tradeAmount <= state.getShortShares(
                        orders[_orderId].userId,
                        orders[_orderId].marketId
                    ).mul(
                        shortShareValue(
                            state.getMeanEntryPrice(orders[_orderId].userId, orders[_orderId].marketId),
                            state.getMeanEntryLeverage(orders[_orderId].userId, orders[_orderId].marketId),
                            state.getLiquidationPrice(orders[_orderId].userId, orders[_orderId].marketId),
                            orders[_orderId].marketPrice,
                            orders[_orderId].marketSpread,
                            PRECISION,
                            true
                    ))
                ) {
                // Partial closing of short position
                orders[_orderId].longSharesOrder = 0;
                orders[_orderId].shortSharesOrder = orders[_orderId].tradeAmount.div(shortShareValue(
                    state.getMeanEntryPrice(orders[_orderId].userId, orders[_orderId].marketId),
                    state.getMeanEntryLeverage(orders[_orderId].userId, orders[_orderId].marketId),
                    state.getLiquidationPrice(orders[_orderId].userId, orders[_orderId].marketId),
                    orders[_orderId].marketPrice,
                    orders[_orderId].marketSpread,
                    PRECISION,
                    true
                ));
            } else {
                // Closing of entire short position
                orders[_orderId].shortSharesOrder = state.getShortShares(orders[_orderId].userId, orders[_orderId].marketId);
                orders[_orderId].longSharesOrder = orders[_orderId].tradeAmount.sub((
                    state.getShortShares(
                        orders[_orderId].userId,
                        orders[_orderId].marketId
                    ).mul(
                        shortShareValue(
                        state.getMeanEntryPrice(orders[_orderId].userId, orders[_orderId].marketId),
                        state.getMeanEntryLeverage(orders[_orderId].userId, orders[_orderId].marketId),
                        state.getLiquidationPrice(orders[_orderId].userId, orders[_orderId].marketId),
                        orders[_orderId].marketPrice,
                        orders[_orderId].marketSpread,
                        PRECISION,
                        true
                    ))
                ));
                orders[_orderId].longSharesOrder = orders[_orderId].longSharesOrder.div(
                    longShareValue(
                        orders[_orderId].marketPrice,
                        orders[_orderId].orderLeverage,
                        0,
                        orders[_orderId].marketPrice,
                        orders[_orderId].marketSpread,
                        orders[_orderId].orderLeverage,
                        false
                ));
            }
        } else {
            // Investment was specified in shares
            if (orders[_orderId].tradeAmount <= state.getShortShares(orders[_orderId].userId, orders[_orderId].marketId)) {
                // Partial closing of short position
                orders[_orderId].longSharesOrder = 0;
                orders[_orderId].shortSharesOrder = orders[_orderId].tradeAmount;
            } else {
                // Closing of entire short position
                orders[_orderId].shortSharesOrder = state.getShortShares(orders[_orderId].userId, orders[_orderId].marketId);
                orders[_orderId].longSharesOrder = orders[_orderId].tradeAmount.sub(
                    state.getShortShares(orders[_orderId].userId, orders[_orderId].marketId)
                );
            }
        }
        // Investment equals number of shares now.
        if (orders[_orderId].shortSharesOrder > 0) {
            closeShort(_orderId);
        }
        if (orders[_orderId].longSharesOrder > 0) {
            openLong(_orderId);
        }
    }

// ----------------------------------------------------------------------------
// processSellOrder(bytes32 _orderId)
// Converts orders specified in virtual shares to orders specified in Morpher token
// and computes the number of long shares that are sold and short shares that are bought.
// short shares are bought only if the order amount exceeds all open long positions
// ----------------------------------------------------------------------------

    function processSellOrder(bytes32 _orderId) private {
        if (orders[_orderId].tradeAmountGivenInShares == false) {
            // Investment was specified in units of MPH
            if (orders[_orderId].tradeAmount <= state.getLongShares(
                    orders[_orderId].userId,
                    orders[_orderId].marketId
                ).mul(
                    longShareValue(
                        state.getMeanEntryPrice(orders[_orderId].userId, orders[_orderId].marketId),
                        state.getMeanEntryLeverage(orders[_orderId].userId, orders[_orderId].marketId),
                        state.getLiquidationPrice(orders[_orderId].userId, orders[_orderId].marketId),
                        orders[_orderId].marketPrice,
                        orders[_orderId].marketSpread,
                        PRECISION,
                        true
                        ))) {
                // Partial closing of long position
                orders[_orderId].shortSharesOrder = 0;
                orders[_orderId].longSharesOrder = orders[_orderId].tradeAmount.div(
                    longShareValue(
                        state.getMeanEntryPrice(orders[_orderId].userId, orders[_orderId].marketId),
                        state.getMeanEntryLeverage(orders[_orderId].userId, orders[_orderId].marketId),
                        state.getLiquidationPrice(orders[_orderId].userId, orders[_orderId].marketId),
                        orders[_orderId].marketPrice,
                        orders[_orderId].marketSpread,
                        PRECISION,
                        true
                ));
            } else {
                // Closing of entire long position
                orders[_orderId].longSharesOrder = state.getLongShares(orders[_orderId].userId, orders[_orderId].marketId);
                orders[_orderId].shortSharesOrder = orders[_orderId].tradeAmount.sub((
                    state.getLongShares(orders[_orderId].userId, orders[_orderId].marketId
                ).mul(
                    longShareValue(
                        state.getMeanEntryPrice(orders[_orderId].userId, orders[_orderId].marketId),
                        state.getMeanEntryLeverage(orders[_orderId].userId,
                        orders[_orderId].marketId),
                        state.getLiquidationPrice(orders[_orderId].userId, orders[_orderId].marketId),
                        orders[_orderId].marketPrice,
                        orders[_orderId].marketSpread,
                        PRECISION,
                        true
                    ))
                ));
                orders[_orderId].shortSharesOrder = orders[_orderId].shortSharesOrder.div(
                    shortShareValue(
                        orders[_orderId].marketPrice,
                        orders[_orderId].orderLeverage,
                        orders[_orderId].marketPrice.mul(100),
                        orders[_orderId].marketPrice,
                        orders[_orderId].marketSpread,
                        orders[_orderId].orderLeverage,
                        false
                ));
            }
        } else {
            // Investment was specified in shares
            if (orders[_orderId].tradeAmount <= state.getLongShares(orders[_orderId].userId, orders[_orderId].marketId)) {
                // Partial closing of long position
                orders[_orderId].shortSharesOrder = 0;
                orders[_orderId].longSharesOrder = orders[_orderId].tradeAmount;
            } else {
                // Closing of entire long position
                orders[_orderId].longSharesOrder = state.getLongShares(orders[_orderId].userId, orders[_orderId].marketId);
                orders[_orderId].shortSharesOrder = orders[_orderId].tradeAmount.sub(
                    state.getLongShares(orders[_orderId].userId, orders[_orderId].marketId)
                );
            }
        }
        // Investment equals number of shares now.
        if (orders[_orderId].longSharesOrder > 0) {
            closeLong(_orderId);
        }
        if (orders[_orderId].shortSharesOrder > 0) {
            openShort(_orderId);
        }
    }

// ----------------------------------------------------------------------------
// openLong(bytes32 _orderId)
// Opens a new long position and computes the new resulting average entry price/spread/leverage.
// Computation is broken down to several instructions for readability.
// ----------------------------------------------------------------------------
    function openLong(bytes32 _orderId) private {
        address _userId = orders[_orderId].userId;
        bytes32 _marketId = orders[_orderId].marketId;

        uint256 _newMeanSpread;
        uint256 _newMeanLeverage;

        // Existing position is virtually liquidated and reopened with current marketPrice
        // orders[_orderId].newMeanEntryPrice = orders[_orderId].marketPrice;
        // _factorLongShares is a factor to adjust the existing longShares via virtual liqudiation and reopening at current market price

        uint256 _factorLongShares = state.getMeanEntryLeverage(_userId, _marketId);
        if (_factorLongShares < PRECISION) {
            _factorLongShares = PRECISION;
        }
        _factorLongShares = _factorLongShares.sub(PRECISION);
        _factorLongShares = _factorLongShares.mul(state.getMeanEntryPrice(_userId, _marketId)).div(orders[_orderId].marketPrice);
        if (state.getMeanEntryLeverage(_userId, _marketId) > _factorLongShares) {
            _factorLongShares = state.getMeanEntryLeverage(_userId, _marketId).sub(_factorLongShares);
        } else {
            _factorLongShares = 0;
        }

        uint256 _adjustedLongShares = _factorLongShares.mul(state.getLongShares(_userId, _marketId)).div(PRECISION);

        // _newMeanLeverage is the weighted leverage of the existing position and the new position
        _newMeanLeverage = state.getMeanEntryLeverage(_userId, _marketId).mul(_adjustedLongShares);
        _newMeanLeverage = _newMeanLeverage.add(orders[_orderId].orderLeverage.mul(orders[_orderId].longSharesOrder));
        _newMeanLeverage = _newMeanLeverage.div(_adjustedLongShares.add(orders[_orderId].longSharesOrder));

        // _newMeanSpread is the weighted spread of the existing position and the new position
        _newMeanSpread = state.getMeanEntrySpread(_userId, _marketId).mul(state.getLongShares(_userId, _marketId));
        _newMeanSpread = _newMeanSpread.add(orders[_orderId].marketSpread.mul(orders[_orderId].longSharesOrder));
        _newMeanSpread = _newMeanSpread.div(_adjustedLongShares.add(orders[_orderId].longSharesOrder));

        orders[_orderId].balanceDown = orders[_orderId].longSharesOrder.mul(orders[_orderId].marketPrice).add(
            orders[_orderId].longSharesOrder.mul(orders[_orderId].marketSpread).mul(orders[_orderId].orderLeverage).div(PRECISION)
        );
        orders[_orderId].balanceUp = 0;
        orders[_orderId].newLongShares = _adjustedLongShares.add(orders[_orderId].longSharesOrder);
        orders[_orderId].newShortShares = state.getShortShares(_userId, _marketId);
        orders[_orderId].newMeanEntryPrice = orders[_orderId].marketPrice;
        orders[_orderId].newMeanEntrySpread = _newMeanSpread;
        orders[_orderId].newMeanEntryLeverage = _newMeanLeverage;

        setPositionInState(_orderId);
    }

// ----------------------------------------------------------------------------
// closeLong(bytes32 _orderId)
// Closes an existing long position. Average entry price/spread/leverage do not change.
// ----------------------------------------------------------------------------
     function closeLong(bytes32 _orderId) private {
        address _userId = orders[_orderId].userId;
        bytes32 _marketId = orders[_orderId].marketId;

        uint256 _newLongShares  = state.getLongShares(_userId, _marketId).sub(orders[_orderId].longSharesOrder);
        uint256 _balanceUp = orders[_orderId].longSharesOrder.mul(longShareValue(
            state.getMeanEntryPrice(_userId, _marketId),
            state.getMeanEntryLeverage(_userId, _marketId),
            state.getLiquidationPrice(_userId, _marketId),
            orders[_orderId].marketPrice, orders[_orderId].marketSpread,
            state.getMeanEntryLeverage(_userId, _marketId),
            true
        ));

        uint256 _newMeanEntry;
        uint256 _newMeanSpread;
        uint256 _newMeanLeverage;

        if (orders[_orderId].longSharesOrder == state.getLongShares(_userId, _marketId)) {
            _newMeanEntry = 0;
            _newMeanSpread = 0;
            _newMeanLeverage = PRECISION;
        } else {
            _newMeanEntry = state.getMeanEntryPrice(_userId, _marketId);
	        _newMeanSpread = state.getMeanEntrySpread(_userId, _marketId);
	        _newMeanLeverage = state.getMeanEntryLeverage(_userId, _marketId);
        }

        orders[_orderId].balanceDown = 0;
        orders[_orderId].balanceUp = _balanceUp;
        orders[_orderId].newLongShares = _newLongShares;
        orders[_orderId].newShortShares = state.getShortShares(_userId, _marketId);
        orders[_orderId].newMeanEntryPrice = _newMeanEntry;
        orders[_orderId].newMeanEntrySpread = _newMeanSpread;
        orders[_orderId].newMeanEntryLeverage = _newMeanLeverage;

        setPositionInState(_orderId);
    }

// ----------------------------------------------------------------------------
// closeShort(bytes32 _orderId)
// Closes an existing short position. Average entry price/spread/leverage do not change.
// ----------------------------------------------------------------------------

    function closeShort(bytes32 _orderId) private {
        address _userId = orders[_orderId].userId;
        bytes32 _marketId = orders[_orderId].marketId;

        uint256 _newMeanEntry;
        uint256 _newMeanSpread;
        uint256 _newMeanLeverage;

        uint256 _newShortShares = state.getShortShares(_userId, _marketId).sub(orders[_orderId].shortSharesOrder);
        uint256 _balanceUp = orders[_orderId].shortSharesOrder.mul(
            shortShareValue(
                state.getMeanEntryPrice(_userId, _marketId),
                state.getMeanEntryLeverage(_userId, _marketId),
                state.getLiquidationPrice(_userId, _marketId),
                orders[_orderId].marketPrice,
                orders[_orderId].marketSpread,
                state.getMeanEntryLeverage(_userId, _marketId),
                true
        ));

        if (orders[_orderId].shortSharesOrder == state.getShortShares(_userId, _marketId)) {
            _newMeanEntry = 0;
            _newMeanSpread = 0;
	        _newMeanLeverage = PRECISION;
        } else {
            _newMeanEntry = state.getMeanEntryPrice(_userId, _marketId);
	        _newMeanSpread = state.getMeanEntrySpread(_userId, _marketId);
	        _newMeanLeverage = state.getMeanEntryLeverage(_userId, _marketId);
        }

        orders[_orderId].balanceDown = 0;
        orders[_orderId].balanceUp = _balanceUp;
        orders[_orderId].newLongShares = state.getLongShares(orders[_orderId].userId, orders[_orderId].marketId);
        orders[_orderId].newShortShares = _newShortShares;
        orders[_orderId].newMeanEntryPrice = _newMeanEntry;
        orders[_orderId].newMeanEntrySpread = _newMeanSpread;
        orders[_orderId].newMeanEntryLeverage = _newMeanLeverage;

        setPositionInState(_orderId);
    }

// ----------------------------------------------------------------------------
// openShort(bytes32 _orderId)
// Opens a new short position and computes the new resulting average entry price/spread/leverage.
// Computation is broken down to several instructions for readability.
// ----------------------------------------------------------------------------
    function openShort(bytes32 _orderId) private {
        address _userId = orders[_orderId].userId;
        bytes32 _marketId = orders[_orderId].marketId;

        uint256 _newMeanSpread;
        uint256 _newMeanLeverage;
        //
        // Existing position is virtually liquidated and reopened with current marketPrice
        // orders[_orderId].newMeanEntryPrice = orders[_orderId].marketPrice;
        // _factorShortShares is a factor to adjust the existing shortShares via virtual liqudiation and reopening at current market price

        uint256 _factorShortShares = state.getMeanEntryLeverage(_userId, _marketId);
        if (_factorShortShares < PRECISION) {
            _factorShortShares = PRECISION;
        }
        _factorShortShares = _factorShortShares.add(PRECISION);
        _factorShortShares = _factorShortShares.mul(state.getMeanEntryPrice(_userId, _marketId)).div(orders[_orderId].marketPrice);
        if (state.getMeanEntryLeverage(_userId, _marketId) < _factorShortShares) {
            _factorShortShares = _factorShortShares.sub(state.getMeanEntryLeverage(_userId, _marketId));
        } else {
            _factorShortShares = 0;
        }

        uint256 _adjustedShortShares = _factorShortShares.mul(state.getShortShares(_userId, _marketId)).div(PRECISION);

        // _newMeanLeverage is the weighted leverage of the existing position and the new position
        _newMeanLeverage = state.getMeanEntryLeverage(_userId, _marketId).mul(_adjustedShortShares);
        _newMeanLeverage = _newMeanLeverage.add(orders[_orderId].orderLeverage.mul(orders[_orderId].shortSharesOrder));
        _newMeanLeverage = _newMeanLeverage.div(_adjustedShortShares.add(orders[_orderId].shortSharesOrder));

        // _newMeanSpread is the weighted spread of the existing position and the new position
        _newMeanSpread = state.getMeanEntrySpread(_userId, _marketId).mul(state.getShortShares(_userId, _marketId));
        _newMeanSpread = _newMeanSpread.add(orders[_orderId].marketSpread.mul(orders[_orderId].shortSharesOrder));
        _newMeanSpread = _newMeanSpread.div(_adjustedShortShares.add(orders[_orderId].shortSharesOrder));

        orders[_orderId].balanceDown = orders[_orderId].shortSharesOrder.mul(orders[_orderId].marketPrice).add(
            orders[_orderId].shortSharesOrder.mul(orders[_orderId].marketSpread).mul(orders[_orderId].orderLeverage).div(PRECISION)
        );
        orders[_orderId].balanceUp = 0;
        orders[_orderId].newLongShares = state.getLongShares(_userId, _marketId);
        orders[_orderId].newShortShares = _adjustedShortShares.add(orders[_orderId].shortSharesOrder);
        orders[_orderId].newMeanEntryPrice = orders[_orderId].marketPrice;
        orders[_orderId].newMeanEntrySpread = _newMeanSpread;
        orders[_orderId].newMeanEntryLeverage = _newMeanLeverage;

        setPositionInState(_orderId);
    }

    function computeLiquidationPrice(bytes32 _orderId) public returns(uint256 _liquidationPrice) {
        orders[_orderId].newLiquidationPrice = 0;
        if (orders[_orderId].newLongShares > 0) {
            orders[_orderId].newLiquidationPrice = getLiquidationPrice(orders[_orderId].newMeanEntryPrice, orders[_orderId].newMeanEntryLeverage, true);
        }
        if (orders[_orderId].newShortShares > 0) {
            orders[_orderId].newLiquidationPrice = getLiquidationPrice(orders[_orderId].newMeanEntryPrice, orders[_orderId].newMeanEntryLeverage, false);
        }
        return orders[_orderId].newLiquidationPrice;
    }

    function getLiquidationPrice(uint256 _newMeanEntryPrice, uint256 _newMeanEntryLeverage, bool _long) public pure returns (uint256 _liquidiationPrice) {
        if (_long == true) {
            _liquidiationPrice = _newMeanEntryPrice.mul(_newMeanEntryLeverage.sub(PRECISION)).div(_newMeanEntryLeverage);
        } else {
            _liquidiationPrice = _newMeanEntryPrice.mul(_newMeanEntryLeverage.add(PRECISION)).div(_newMeanEntryLeverage);
        }
        return _liquidiationPrice;
    }

// ----------------------------------------------------------------------------
// setPositionInState(bytes32 _orderId)
// Updates the portfolio in Morpher State. Called by closeLong/closeShort/openLong/openShort
// ----------------------------------------------------------------------------
    function setPositionInState(bytes32 _orderId) private {
        require(state.balanceOf(orders[_orderId].userId).add(orders[_orderId].balanceUp) >= orders[_orderId].balanceDown, "MorpherTradeEngine: insufficient funds.");
        computeLiquidationPrice(_orderId);
        // Net balanceUp and balanceDown
        if (orders[_orderId].balanceUp > orders[_orderId].balanceDown) {
            orders[_orderId].balanceUp.sub(orders[_orderId].balanceDown);
            orders[_orderId].balanceDown = 0;
        } else {
            orders[_orderId].balanceDown.sub(orders[_orderId].balanceUp);
            orders[_orderId].balanceUp = 0;
        }
        if (orders[_orderId].balanceUp > 0) {
            state.mint(orders[_orderId].userId, orders[_orderId].balanceUp);
        }
        if (orders[_orderId].balanceDown > 0) {
            state.burn(orders[_orderId].userId, orders[_orderId].balanceDown);
        }
        state.setPosition(
            orders[_orderId].userId,
            orders[_orderId].marketId,
            orders[_orderId].timeStamp,
            orders[_orderId].newLongShares,
            orders[_orderId].newShortShares,
            orders[_orderId].newMeanEntryPrice,
            orders[_orderId].newMeanEntrySpread,
            orders[_orderId].newMeanEntryLeverage,
            orders[_orderId].newLiquidationPrice
        );
        emit PositionUpdated(
            orders[_orderId].userId,
            orders[_orderId].marketId,
            orders[_orderId].timeStamp,
            orders[_orderId].newLongShares,
            orders[_orderId].newShortShares,
            orders[_orderId].newMeanEntryPrice,
            orders[_orderId].newMeanEntrySpread,
            orders[_orderId].newMeanEntryLeverage,
            orders[_orderId].newLiquidationPrice,
            orders[_orderId].balanceUp,
            orders[_orderId].balanceDown
        );
    }
}

File 14 of 15: Ownable.sol
pragma solidity 0.5.16;

import "./IERC20.sol";

/**
 * @title Ownable
 * @dev The Ownable contract has an owner address, and provides basic authorization control
 * functions, this simplifies the implementation of "user permissions".
 */
contract Ownable {
    address public _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev The Ownable constructor sets the original `owner` of the contract to the sender
     * account.
     */
    constructor () internal {
        _owner = msg.sender;
        emit OwnershipTransferred(address(0), _owner);
    }

    /**
     * @return the address of the owner.
     */
    function owner() public view returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(isOwner(), "Ownable: caller should be owner.");
        _;
    }

    /**
     * @return true if `msg.sender` is the owner of the contract.
     */
    function isOwner() public view returns (bool) {
        return msg.sender == _owner;
    }

    /**
     * @dev Allows the current owner to relinquish control of the contract.
     * It will not be possible to call the functions with the `onlyOwner`
     * modifier anymore.
     * @notice Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @dev Allows the current owner to transfer control of the contract to a newOwner.
     * @param newOwner The address to transfer ownership to.
     */
    function transferOwnership(address newOwner) public onlyOwner {
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers control of the contract to a newOwner.
     * @param newOwner The address to transfer ownership to.
     */
    function _transferOwnership(address newOwner) internal {
        require(newOwner != address(0), "Ownable: use renounce ownership instead.");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
    // ------------------------------------------------------------------------
    // Owner can transfer out any accidentally sent ERC20 tokens
    // ------------------------------------------------------------------------
    function transferAnyERC20Token(address _tokenAddress, uint256 _tokens) public onlyOwner returns (bool _success) {
        return IERC20(_tokenAddress).transfer(owner(), _tokens);
    }
}

File 15 of 15: SafeMath.sol
pragma solidity 0.5.16;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     *
     * _Available since v2.4.0._
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     *
     * _Available since v2.4.0._
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     *
     * _Available since v2.4.0._
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"bool","name":"_mainChain","type":"bool"},{"internalType":"address","name":"_sideChainOperator","type":"address"},{"internalType":"address","name":"_morpherTreasury","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"administratorAddress","type":"address"}],"name":"AdministratorChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_bridgeAddress","type":"address"}],"name":"BridgeChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalToken","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[],"name":"FastWithdrawsDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"governanceAddress","type":"address"}],"name":"GovernanceChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_periodLength","type":"uint256"}],"name":"InactivityPeriodUpdated","type":"event"},{"anonymous":false,"inputs":[],"name":"Last24HoursAmountWithdrawnReset","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"rewardsTime","type":"uint256"}],"name":"LastRewardTime","type":"event"},{"anonymous":false,"inputs":[],"name":"LastWithdrawAt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"mainChainWithdrawLimit24","type":"uint256"}],"name":"MainChainWithdrawLimitUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"activateMarket","type":"bytes32"}],"name":"MarketActivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"deActivateMarket","type":"bytes32"}],"name":"MarketDeActivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxLeverage","type":"uint256"}],"name":"MaximumLeverageChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalToken","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_transferNonce","type":"uint256"}],"name":"NewBridgeNonce","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sideChainOperator","type":"address"}],"name":"NewSideChainOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newTotalOnOtherChain","type":"uint256"}],"name":"NewTotalInPositions","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newTotalOnOtherChain","type":"uint256"}],"name":"NewTotalOnOtherChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newTotalSupply","type":"uint256"}],"name":"NewTotalSupply","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_numberOfRequests","type":"uint256"}],"name":"NumberOfRequestsLimitUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"OperatingRewardMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oracleContract","type":"address"}],"name":"OracleChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"rewardsAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"rewardsBasisPoints","type":"uint256"}],"name":"RewardsChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_last24HoursAmountWithdrawn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_lastWithdrawLimitReductionTime","type":"uint256"}],"name":"RollingWithdrawnAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokens","type":"uint256"}],"name":"SetAllowance","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"balance","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"balanceHash","type":"bytes32"}],"name":"SetBalance","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"positionHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"bytes32","name":"marketId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"timeStamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"longShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shortShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"meanEntryPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"meanEntrySpread","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"meanEntryLeverage","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"liquidationPrice","type":"uint256"}],"name":"SetPosition","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"sideChainMerkleRoot","type":"bytes32"}],"name":"SideChainMerkleRootUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"blackList","type":"address"},{"indexed":true,"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"StateAccessDenied","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"whiteList","type":"address"},{"indexed":true,"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"StateAccessGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"administrator","type":"address"},{"indexed":false,"internalType":"bool","name":"_paused","type":"bool"}],"name":"StatePaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"}],"name":"TokenChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_address","type":"address"},{"indexed":false,"internalType":"uint256","name":"_token","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_totalTokenSent","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"_tokenSentToLinkedChainHash","type":"bytes32"}],"name":"TokenSentToLinkedChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenTransferredToOtherChain","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"transferHash","type":"bytes32"}],"name":"TokenTransferredToOtherChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_address","type":"address"},{"indexed":false,"internalType":"uint256","name":"_token","type":"uint256"}],"name":"TransferredTokenClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"blackList","type":"address"}],"name":"TransfersDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"whiteList","type":"address"}],"name":"TransfersEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"WithdrawLimitUpdated","type":"event"},{"constant":true,"inputs":[],"name":"_owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_activateMarket","type":"bytes32"}],"name":"activateMarket","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"add24HoursWithdrawn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"administrator","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_tokenOwner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"_token","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_deActivateMarket","type":"bytes32"}],"name":"deActivateMarket","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"denyAccess","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"disableFastWithdraws","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"disableTransfers","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"enableTransfers","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"fastTransfersEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getAdministrator","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_tokenOwner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"getAllowance","outputs":[{"internalType":"uint256","name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"_balance","type":"uint256"}],"name":"getBalanceHash","outputs":[{"internalType":"bytes32","name":"_hash","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"getBridgeNonce","outputs":[{"internalType":"uint256","name":"_nonce","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getCanTransfer","outputs":[{"internalType":"bool","name":"_hasAccess","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"uint256","name":"_mappingIndex","type":"uint256"}],"name":"getExposureMappingAddress","outputs":[{"internalType":"address","name":"_address","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"address","name":"_address","type":"address"}],"name":"getExposureMappingIndex","outputs":[{"internalType":"uint256","name":"_mappingIndex","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getGovernance","outputs":[{"internalType":"address","name":"_governanceContract","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getLastRequestBlock","outputs":[{"internalType":"uint256","name":"_lastRequestBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getLastUpdated","outputs":[{"internalType":"uint256","name":"_lastUpdated","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getLiquidationPrice","outputs":[{"internalType":"uint256","name":"_liquidationPrice","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getLongShares","outputs":[{"internalType":"uint256","name":"_longShares","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getMainChainWithdrawLimit","outputs":[{"internalType":"uint256","name":"_mainChainWithdrawLimit24","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getMarketActive","outputs":[{"internalType":"bool","name":"_active","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getMaxMappingIndex","outputs":[{"internalType":"uint256","name":"_maxMappingIndex","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getMaximumLeverage","outputs":[{"internalType":"uint256","name":"_maxLeverage","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getMeanEntryLeverage","outputs":[{"internalType":"uint256","name":"_meanEntryLeverage","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getMeanEntryPrice","outputs":[{"internalType":"uint256","name":"_meanEntryPrice","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getMeanEntrySpread","outputs":[{"internalType":"uint256","name":"_meanEntrySpread","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getMorpherBridge","outputs":[{"internalType":"address","name":"_currentBridge","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getNumberOfRequests","outputs":[{"internalType":"uint256","name":"_numberOfRequests","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNumberOfRequestsLimit","outputs":[{"internalType":"uint256","name":"_numberOfRequestsLimit","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getOracleContract","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getPosition","outputs":[{"internalType":"uint256","name":"_longShares","type":"uint256"},{"internalType":"uint256","name":"_shortShares","type":"uint256"},{"internalType":"uint256","name":"_meanEntryPrice","type":"uint256"},{"internalType":"uint256","name":"_meanEntrySpread","type":"uint256"},{"internalType":"uint256","name":"_meanEntryLeverage","type":"uint256"},{"internalType":"uint256","name":"_liquidationPrice","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"_positionHash","type":"bytes32"}],"name":"getPositionClaimedOnMainChain","outputs":[{"internalType":"bool","name":"_alreadyClaimed","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"uint256","name":"_timeStamp","type":"uint256"},{"internalType":"uint256","name":"_longShares","type":"uint256"},{"internalType":"uint256","name":"_shortShares","type":"uint256"},{"internalType":"uint256","name":"_meanEntryPrice","type":"uint256"},{"internalType":"uint256","name":"_meanEntrySpread","type":"uint256"},{"internalType":"uint256","name":"_meanEntryLeverage","type":"uint256"},{"internalType":"uint256","name":"_liquidationPrice","type":"uint256"}],"name":"getPositionHash","outputs":[{"internalType":"bytes32","name":"_hash","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getShortShares","outputs":[{"internalType":"uint256","name":"_shortShares","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getSideChainMerkleRoot","outputs":[{"internalType":"bytes32","name":"_sideChainMerkleRoot","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getSideChainMerkleRootWrittenAtTime","outputs":[{"internalType":"uint256","name":"_sideChainMerkleRoot","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getSideChainOperator","outputs":[{"internalType":"address","name":"_address","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getStateAccess","outputs":[{"internalType":"bool","name":"_hasAccess","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getTokenClaimedOnThisChain","outputs":[{"internalType":"uint256","name":"_token","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTokenContract","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getTokenSentToLinkedChain","outputs":[{"internalType":"uint256","name":"_token","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getTokenSentToLinkedChainTime","outputs":[{"internalType":"uint256","name":"_timeStamp","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"grantAccess","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"inactivityPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"increaseNumberOfRequests","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"last24HoursAmountWithdrawn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastRewardTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastWithdrawLimitReductionTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"mainChain","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"mainChainWithdrawLimit24","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maximumLeverage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"_token","type":"uint256"}],"name":"mint","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"morpherBridge","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"morpherGovernance","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"morpherRewards","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"morpherToken","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"numberOfRequestsLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"oracleContract","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pauseState","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"payOperatingReward","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"resetLast24HoursAmountWithdrawn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"rewardBasisPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"set24HourWithdrawLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_newAdministrator","type":"address"}],"name":"setAdministrator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_tokens","type":"uint256"}],"name":"setAllowance","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"setExposureMapping","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"setExposureMappingAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"setExposureMappingIndex","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_newGovernanceContractAddress","type":"address"}],"name":"setGovernanceContract","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_periodLength","type":"uint256"}],"name":"setInactivityPeriod","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"setLastRequestBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_mainChainWithdrawLimit24","type":"uint256"}],"name":"setMainChainWithdrawLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"uint256","name":"_maxMappingIndex","type":"uint256"}],"name":"setMaxMappingIndex","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_newMaximumLeverage","type":"uint256"}],"name":"setMaximumLeverage","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_newBridge","type":"address"}],"name":"setMorpherBridge","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"_numberOfRequests","type":"uint256"}],"name":"setNumberOfRequests","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_numberOfRequestsLimit","type":"uint256"}],"name":"setNumberOfRequestsLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_newOracleContract","type":"address"}],"name":"setOracleContract","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"uint256","name":"_timeStamp","type":"uint256"},{"internalType":"uint256","name":"_longShares","type":"uint256"},{"internalType":"uint256","name":"_shortShares","type":"uint256"},{"internalType":"uint256","name":"_meanEntryPrice","type":"uint256"},{"internalType":"uint256","name":"_meanEntrySpread","type":"uint256"},{"internalType":"uint256","name":"_meanEntryLeverage","type":"uint256"},{"internalType":"uint256","name":"_liquidationPrice","type":"uint256"}],"name":"setPosition","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_positionHash","type":"bytes32"}],"name":"setPositionClaimedOnMainChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_newRewardsAddress","type":"address"}],"name":"setRewardAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_newRewardBasisPoints","type":"uint256"}],"name":"setRewardBasisPoints","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_sideChainMerkleRoot","type":"bytes32"}],"name":"setSideChainMerkleRoot","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"setSideChainOperator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"_token","type":"uint256"}],"name":"setTokenClaimedOnThisChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_newTokenContract","type":"address"}],"name":"setTokenContract","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"_token","type":"uint256"}],"name":"setTokenSentToLinkedChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_totalInPositions","type":"uint256"}],"name":"setTotalInPositions","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_newTotalOnOtherChain","type":"uint256"}],"name":"setTotalOnOtherChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"sideChainMerkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"sideChainMerkleRootWrittenAtTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"sideChainOperator","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalInPositions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalOnOtherChain","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_token","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_tokens","type":"uint256"}],"name":"transferAnyERC20Token","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"transferNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unPauseState","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"update24HoursWithdrawLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"withdrawLimit24Hours","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]

6080604052633b9aca006005556006805460ff191690556a108b2a2c280290940000006011556203f4806020553480156200003957600080fd5b5060405162004e9838038062004e98833981810160405260608110156200005f57600080fd5b5080516020820151604092830151600080546001600160a01b031916331780825594519394929391926001600160a01b0316917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36000805460ff60a01b1916600160a01b85151502179055620000d9426200038c565b6b01dba0fc757e49bc9f0000006b015f8d402a52368049000000620001196200010a6001600160e01b03620003bf16565b6001600160e01b03620003ce16565b6200013f620001306001600160e01b03620003bf16565b6001600160e01b036200047016565b600054600160a01b900460ff1662000235578160146000620001696001600160e01b03620003bf16565b6001600160a01b0316815260208101919091526040016000205560028290556200019b6001600160e01b03620003bf16565b6001600160a01b031660008051602062004ddd833981519152620001da620001cb6001600160e01b03620003bf16565b6001600160e01b036200050e16565b60408051918252602082018690528051918290030190a26200020660006001600160e01b036200052916565b6200021b60006001600160e01b036200065d16565b6200022f816001600160e01b036200070116565b62000304565b80601460006200024d6001600160e01b03620003bf16565b6001600160a01b0316815260208101919091526040016000205560028190556200027f6001600160e01b03620003bf16565b6001600160a01b031660008051602062004ddd833981519152620002af620001cb6001600160e01b03620003bf16565b60408051918252602082018590528051918290030190a2620002dc613a986001600160e01b036200052916565b620002f0836001600160e01b036200065d16565b62000304826001600160e01b036200070116565b6022805460ff191660011790556200032660036001600160e01b036200079a16565b620003476032600154816200033757fe5b046001600160e01b036200082a16565b6200035b846001600160e01b036200047016565b62000381620003726001600160e01b03620003bf16565b6001600160e01b03620008b116565b505050505062000a35565b600e81905560405181907fb11f7283fda904f54a0fc8af727d3bf56e40a6cbf7c8fbb177083f0a335152ed90600090a250565b6000546001600160a01b031690565b620003e16001600160e01b036200095016565b62000422576040805162461bcd60e51b8152602060048201819052602482015260008051602062004e78833981519152604482015290519081900360640190fd5b6001600160a01b038116600081815260126020526040808220805460ff19166001179055514392917f556646edb498605e1eaf0f4ab1619f3dbc4164f1cddc22ecae584e045838d13891a350565b620004836001600160e01b036200095016565b620004c4576040805162461bcd60e51b8152602060048201819052602482015260008051602062004e78833981519152604482015290519081900360640190fd5b600a80546001600160a01b0319166001600160a01b0383169081179091556040517f07c5be40db03f5890f6ca87fc24a286cabbbd63a79791089701cb0b5eb71529890600090a250565b6001600160a01b031660009081526014602052604090205490565b6200053c6001600160e01b036200095016565b6200057d576040805162461bcd60e51b8152602060048201819052602482015260008051602062004e78833981519152604482015290519081900360640190fd5b600054600160a01b900460ff16151560011415620005de57613a98811115620005d85760405162461bcd60e51b815260040180806020018281038252604481526020018062004d5d6044913960600191505060405180910390fd5b6200061d565b80156200061d5760405162461bcd60e51b815260040180806020018281038252603e81526020018062004e3a603e913960400191505060405180910390fd5b600d81905560075460405182916001600160a01b0316907faa735ef3e20d6d58610022edb69ae0e7e8aaa0084dc5699a0b36a5683bc7a7c790600090a350565b620006706001600160e01b036200095016565b620006b1576040805162461bcd60e51b8152602060048201819052602482015260008051602062004e78833981519152604482015290519081900360640190fd5b600780546001600160a01b0319166001600160a01b038316908117909155600d546040519091907faa735ef3e20d6d58610022edb69ae0e7e8aaa0084dc5699a0b36a5683bc7a7c790600090a350565b600a546001600160a01b031633146200074c5760405162461bcd60e51b815260040180806020018281038252603d81526020018062004dfd603d913960400191505060405180910390fd5b6004819055620007646001600160e01b036200096116565b6040805182815290517f38e3203d00fb51f959df7882c56c583370da2f7abea215c09e83e7ffa61281d29181900360200190a150565b3360009081526012602052604090205460ff161515600114620007ef5760405162461bcd60e51b815260040180806020018281038252603c81526020018062004da1603c913960400191505060405180910390fd5b60258190556040805182815290517f8347cc6d3a3b991db61121237578d3a133ddf434ee43936f1c48d2c815eb0ab39181900360200190a150565b6200083d6001600160e01b036200095016565b6200087e576040805162461bcd60e51b8152602060048201819052602482015260008051602062004e78833981519152604482015290519081900360640190fd5b601181905560405181907f1177d9c2a77eb9dd45c02329c8e4924e44101d64dabf8024543b0ce26e622f3690600090a250565b620008c46001600160e01b036200095016565b62000905576040805162461bcd60e51b8152602060048201819052602482015260008051602062004e78833981519152604482015290519081900360640190fd5b6001600160a01b038116600081815260126020526040808220805460ff19169055514392917fa40f23a963aabba33c55679497d6dd6d9815feadbeb0b0ad39d1285beda16bdd91a350565b6000546001600160a01b0316331490565b6200099a60045462000986600354600254620009d360201b62003c1a1790919060201c565b620009d360201b62003c1a1790919060201c565b600181905560408051918252517f5b1767df4e2cc8a7b2716959e609e0cdd987c9b88ac27b7fc4be99435aa1673b9181900360200190a1565b60008282018381101562000a2e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6143188062000a456000396000f3fe608060405234801561001057600080fd5b50600436106106e05760003560e01c80637c995e9111610387578063bfde5730116101de578063e4974f8d1161010f578063f2fde38b116100ad578063faddee1411610087578063faddee1414611292578063fbfc50f6146112be578063fc89a4fc146112c6578063ff047c38146112e3576106e0565b8063f2fde38b1461125c578063f53d0a8e14611282578063f606a41a1461128a576106e0565b8063ebd164fb116100e9578063ebd164fb146111c1578063ef5fa322146111e7578063ef92f83114611213578063efeecb0414611230576106e0565b8063e4974f8d14611194578063e4bd85221461119c578063e5160f80146111a4576106e0565b8063d8d5470d1161017c578063dc39d06d11610156578063dc39d06d1461110e578063df8089ef1461113a578063e291f13514611160578063e3bbb5651461118c576106e0565b8063d8d5470d146110b3578063da46098c146110bb578063da4b0f40146110f1576106e0565b8063c5e1b59a116101b8578063c5e1b59a14611060578063d362bd2b14611086578063d69082c41461108e578063d7118351146110ab576106e0565b8063bfde573014611015578063c209afac1461101d578063c5d90a1914611043576106e0565b8063aa43ced8116102b8578063b8ed12a411610256578063bcc3e34211610230578063bcc3e34214610f59578063be7e64b614610f7f578063beabacc814610fd7578063bece75321461100d576106e0565b8063b8ed12a414610f23578063bb65b24214610f2b578063bbcd5bbe14610f33576106e0565b8063acb17ba711610292578063acb17ba714610ebb578063af434a6d14610ee1578063b2bdfa7b14610efe578063b6554c2c14610f06576106e0565b8063aa43ced814610e8e578063aa7bcd5d14610e96578063ac981b1e14610e9e576106e0565b80639231cf7411610325578063a0580880116102ff578063a058088014610e2f578063a35ab9c814610e37578063a8c8afaa14610e54578063a99d389f14610e5c576106e0565b80639231cf7414610dde5780639dc29fac14610de65780639fe4e9d214610e12576106e0565b80638da5cb5b116103615780638da5cb5b14610d765780638ea09da614610d7e5780638f32d59b14610da45780639162298f14610dac576106e0565b80637c995e9114610d3a578063857b0da014610d425780638c4050b114610d6e576106e0565b80633d7f4f3c1161053b57806361afd5ac1161046c578063706277da1161040a57806373ed1fe2116103e457806373ed1fe214610cca578063755ca87a14610cd25780637a68744414610cda5780637b431ab114610d32576106e0565b8063706277da14610c9457806370a0823114610c9c578063715018a614610cc2576106e0565b806369c66c7b1161044657806369c66c7b14610c1757806369cdcfb714610c435780636c36a4ec14610c605780636d37e21814610c8c576106e0565b806361afd5ac14610bbd578063626be56714610be3578063652f176314610beb576106e0565b80634da3c199116104d95780635996e209116104b35780635996e20914610b615780635c8b933414610b695780635c975abb14610b8f5780635e00e67914610b97576106e0565b80634da3c19914610b3457806355b3374114610b51578063592b6aab14610b59576106e0565b8063422cc2e711610515578063422cc2e714610aa857806344ae029c14610ad4578063496ccd9b14610af15780634a4cce9714610b17576106e0565b80633d7f4f3c14610a485780633eedf76a14610a7457806340c10f1914610a7c576106e0565b8063169674071161061557806321c02c8e116105b357806328b7bede1161058d57806328b7bede146109cb5780632d7b42c1146109d35780633383e8d8146109f6578063364ae26e14610a22576106e0565b806321c02c8e1461099557806325fbf712146109bb578063289b3c0d146109c3576106e0565b80631864ba30116105ef5780631864ba30146109365780631bdbae90146109625780631cb110771461096a5780632020e69714610972576106e0565b806316967407146108f4578063174c51dc146108fc57806318160ddd1461092e576106e0565b80630b7c8e7f116106825780630fa8f5161161065c5780630fa8f516146108235780631129753f1461088257806314712512146108a857806314ce70ef146108ce576106e0565b80630b7c8e7f146107d95780630eb933dc146107e15780630f508e001461081b576106e0565b806309089f97116106be57806309089f97146107475780630aa7cee2146107615780630ae5e739146107855780630af4187d146107ab576106e0565b806304371f48146106e557806306442d0a1461070457806307a9100e14610721575b600080fd5b610702600480360360208110156106fb57600080fd5b50356112eb565b005b6107026004803603602081101561071a57600080fd5b503561140c565b6107026004803603602081101561073757600080fd5b50356001600160a01b03166114a3565b61074f611512565b60408051918252519081900360200190f35b6107696115af565b604080516001600160a01b039092168252519081900360200190f35b6107026004803603602081101561079b57600080fd5b50356001600160a01b03166115be565b61074f600480360360408110156107c157600080fd5b506001600160a01b0381358116916020013516611653565b61074f611680565b610807600480360360208110156107f757600080fd5b50356001600160a01b0316611686565b604080519115158252519081900360200190f35b6107696116a4565b61084f6004803603604081101561083957600080fd5b506001600160a01b0381351690602001356116b3565b604080519687526020870195909552858501939093526060850191909152608084015260a0830152519081900360c00190f35b6107026004803603602081101561089857600080fd5b50356001600160a01b0316611700565b610807600480360360208110156108be57600080fd5b50356001600160a01b0316611799565b610702600480360360208110156108e457600080fd5b50356001600160a01b03166117b7565b610769611848565b6107026004803603606081101561091257600080fd5b508035906001600160a01b036020820135169060400135611857565b61074f6118e7565b61074f6004803603604081101561094c57600080fd5b506001600160a01b0381351690602001356118ed565b61074f611918565b61074f61191e565b6107026004803603604081101561098857600080fd5b5080359060200135611924565b61074f600480360360208110156109ab57600080fd5b50356001600160a01b0316611989565b61074f6119a4565b6107696119aa565b6107696119be565b610769600480360360408110156109e957600080fd5b50803590602001356119cd565b61070260048036036040811015610a0c57600080fd5b506001600160a01b0381351690602001356119f7565b61074f60048036036020811015610a3857600080fd5b50356001600160a01b0316611aa7565b61074f60048036036040811015610a5e57600080fd5b506001600160a01b038135169060200135611ac2565b61074f611aea565b61070260048036036040811015610a9257600080fd5b506001600160a01b038135169060200135611af0565b61070260048036036040811015610abe57600080fd5b506001600160a01b038135169060200135611d14565b61080760048036036020811015610aea57600080fd5b5035611dfa565b61070260048036036020811015610b0757600080fd5b50356001600160a01b0316611e0f565b61080760048036036020811015610b2d57600080fd5b5035611eb0565b61070260048036036020811015610b4a57600080fd5b5035611ec5565b61074f611f53565b610702611f59565b610702611fe5565b61074f60048036036020811015610b7f57600080fd5b50356001600160a01b0316612083565b61080761209e565b61070260048036036020811015610bad57600080fd5b50356001600160a01b03166120a7565b61070260048036036020811015610bd357600080fd5b50356001600160a01b031661213e565b61074f6121d0565b61074f60048036036040811015610c0157600080fd5b506001600160a01b0381351690602001356121d6565b61074f60048036036040811015610c2d57600080fd5b50803590602001356001600160a01b0316612201565b61070260048036036020811015610c5957600080fd5b503561222d565b61070260048036036040811015610c7657600080fd5b506001600160a01b0381351690602001356122a7565b610702612316565b61076961242b565b61074f60048036036020811015610cb257600080fd5b50356001600160a01b031661243a565b610702612455565b6107696124e6565b61074f6124f5565b61074f6004803603610120811015610cf157600080fd5b506001600160a01b038135169060208101359060408101359060608101359060808101359060a08101359060c08101359060e08101359061010001356124fb565b61074f612573565b61074f612579565b61074f60048036036040811015610d5857600080fd5b506001600160a01b03813516906020013561257f565b61074f6125c3565b6107696125c9565b61070260048036036020811015610d9457600080fd5b50356001600160a01b03166125d8565b610807612668565b61070260048036036060811015610dc257600080fd5b508035906001600160a01b036020820135169060400135612679565b61074f6126e7565b61070260048036036040811015610dfc57600080fd5b506001600160a01b0381351690602001356126ed565b61070260048036036020811015610e2857600080fd5b503561292d565b6107026129bb565b61070260048036036020811015610e4d57600080fd5b5035612a42565b610769612b0c565b61070260048036036060811015610e7257600080fd5b508035906001600160a01b036020820135169060400135612b20565b61074f612b9d565b61074f612ba3565b61070260048036036020811015610eb457600080fd5b5035612ba9565b61070260048036036020811015610ed157600080fd5b50356001600160a01b0316612c43565b61070260048036036020811015610ef757600080fd5b5035612cd6565b610769612d69565b61070260048036036020811015610f1c57600080fd5b5035612d78565b61074f612dea565b61074f612df0565b61070260048036036020811015610f4957600080fd5b50356001600160a01b0316612df6565b61070260048036036020811015610f6f57600080fd5b50356001600160a01b0316612e87565b6107026004803603610120811015610f9657600080fd5b506001600160a01b038135169060208101359060408101359060608101359060808101359060a08101359060c08101359060e0810135906101000135612efa565b61070260048036036060811015610fed57600080fd5b506001600160a01b03813581169160208101359091169060400135613091565b6107696133a3565b6108076133b2565b61074f6004803603602081101561103357600080fd5b50356001600160a01b03166133c2565b6107026004803603602081101561105957600080fd5b50356133dd565b6107026004803603602081101561107657600080fd5b50356001600160a01b0316613469565b61074f613504565b610702600480360360208110156110a457600080fd5b503561350a565b6107026135ba565b61080761365e565b610702600480360360608110156110d157600080fd5b506001600160a01b03813581169160208101359091169060400135613667565b6107026004803603602081101561110757600080fd5b503561371c565b6108076004803603604081101561112457600080fd5b506001600160a01b0381351690602001356137f0565b6107026004803603602081101561115057600080fd5b50356001600160a01b03166138d3565b61074f6004803603604081101561117657600080fd5b506001600160a01b038135169060200135613974565b61076961399f565b6107696139ae565b61074f6139bd565b610702600480360360208110156111ba57600080fd5b50356139c3565b61074f600480360360208110156111d757600080fd5b50356001600160a01b0316613a5d565b61074f600480360360408110156111fd57600080fd5b506001600160a01b038135169060200135613a78565b61074f6004803603602081101561122957600080fd5b5035613aa3565b61074f6004803603604081101561124657600080fd5b506001600160a01b038135169060200135613ab5565b6107026004803603602081101561127257600080fd5b50356001600160a01b0316613ae0565b610769613b33565b610769613b42565b61074f600480360360408110156112a857600080fd5b506001600160a01b038135169060200135613b51565b61074f613b7c565b610702600480360360208110156112dc57600080fd5b5035613b82565b61074f613c14565b6112f3612668565b611332576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600054600160a01b900460ff1615156001141561138f57613a9881111561138a5760405162461bcd60e51b81526004018080602001828103825260448152602001806140876044913960600191505060405180910390fd5b6113cc565b80156113cc5760405162461bcd60e51b815260040180806020018281038252603e815260200180614227603e913960400191505060405180910390fd5b600d81905560075460405182916001600160a01b0316907faa735ef3e20d6d58610022edb69ae0e7e8aaa0084dc5699a0b36a5683bc7a7c790600090a350565b611414611848565b6001600160a01b0316336001600160a01b0316146114635760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b600081815260166020526040808220805460ff191690555182917f9cb9d54a58b209894faa9f115e54b1c61733c0764fe29ed01f97c7c425f2f24391a250565b3360009081526012602052604090205460ff1615156001146114f65760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6001600160a01b03166000908152602360205260409020439055565b600061151c6124e6565b6001600160a01b0316336001600160a01b03161461156b5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b602180546001019081905560408051918252517f86423ef8971dc4252acb273ac1099fb639020a7a2f5a64dad077d033ab2ae8e29181900360200190a15060215490565b600a546001600160a01b031681565b6115c6612668565b611605576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b6001600160a01b038116600081815260126020526040808220805460ff19166001179055514392917f556646edb498605e1eaf0f4ab1619f3dbc4164f1cddc22ecae584e045838d13891a350565b6001600160a01b038083166000908152601560209081526040808320938516835292905220545b92915050565b60035481565b6001600160a01b031660009081526013602052604090205460ff1690565b600a546001600160a01b031690565b6001600160a01b0391909116600090815260176020908152604080832093835292905220600181015460028201546003830154600484015460058501546006909501549395929491939092565b611708612668565b611747576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b60068054610100600160a81b0319166101006001600160a01b038416908102919091179091556040517f5ab1e8b2c0a96bffa69cb323894590e00556bdce76b87d529100949740e6a55a90600090a250565b6001600160a01b031660009081526012602052604090205460ff1690565b6117bf612668565b6117fe576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600a80546001600160a01b0319166001600160a01b0383169081179091556040517f07c5be40db03f5890f6ca87fc24a286cabbbd63a79791089701cb0b5eb71529890600090a250565b6008546001600160a01b031690565b3360009081526012602052604090205460ff1615156001146118aa5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60009283526018602090815260408085209285526002909201905290912080546001600160a01b0319166001600160a01b03909216919091179055565b60015481565b6001600160a01b03919091166000908152601760209081526040808320938352929052206002015490565b60045481565b601f5481565b3360009081526012602052604090205460ff1615156001146119775760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60009182526018602052604090912055565b6001600160a01b031660009081526019602052604090205490565b600f5490565b60065461010090046001600160a01b031690565b600c546001600160a01b031690565b6000918252601860209081526040808420928452600290920190529020546001600160a01b031690565b6119ff6124e6565b6001600160a01b0316336001600160a01b031614611a4e5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b6001600160a01b0382166000818152601960209081526040918290208490558151928352820183905280517fb83fc1206022cf828cdd927bea92f3cfe9ae485bc4d4308b65413dfdd0ab6edb9281900390910190a15050565b6001600160a01b03166000908152601a602052604090205490565b6001600160a01b03919091166000908152601760209081526040808320938352929052205490565b60055481565b3360009081526012602052604090205460ff161515600114611b435760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60065460ff1615611b855760405162461bcd60e51b815260040180806020018281038252602781526020018061429d6027913960400191505060405180910390fd5b6001600160a01b038216600090815260146020526040902054611bae908263ffffffff613c1a16565b6001600160a01b038316600090815260146020526040902055600254611bda908263ffffffff613c1a16565b600255611be5613c7b565b600c54604080516323de665160e01b81526000600482018190526001600160a01b03868116602484015260448301869052925192909316926323de66519260648084019382900301818387803b158015611c3e57600080fd5b505af1158015611c52573d6000803e3d6000fd5b505060025460408051858152602081019290925280516001600160a01b03871694507f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f9350918290030190a26001600160a01b038216600090815260146020526040902054611cc290839061257f565b6001600160a01b03831660008181526014602090815260409182902054825190815291517fd5cc1526bf6f20f18608ca8834d23bacab6780c93fa2e5e7033a5c85016af0469281900390910190a35050565b611d1c6124e6565b6001600160a01b0316336001600160a01b031614611d6b5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b6001600160a01b0382166000908152601a60208181526040808420858155601b835293204290555254611d9f90839061257f565b6001600160a01b0383166000818152601a602090815260409182902054825193845290830185905282820152517fa3579111956ed8ebf7836e375375f707ea762883fa60008df45a289d53090b659181900360600190a25050565b6000908152601c602052604090205460ff1690565b611e176119aa565b6001600160a01b0316336001600160a01b031614611e665760405162461bcd60e51b815260040180806020018281038252604581526020018061412e6045913960600191505060405180910390fd5b600980546001600160a01b0319166001600160a01b0383169081179091556040517f127863dda9b4c03043886af0affd8e8ff8c0c65822d70f0b639eadce57271f0890600090a250565b60009081526016602052604090205460ff1690565b611ecd6124e6565b6001600160a01b0316336001600160a01b031614611f1c5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b600f8190554260105560405181907f2fe11f024562cd0798f5b3975c7be128c3b86e0249f9a66ad1e74bfb52f9246490600090a250565b60115481565b611f616124e6565b6001600160a01b0316336001600160a01b031614611fb05760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b6022805460ff191690556040517ff6b2b9c63998bbfbe0a548dce3fa97702cb864dbfbdb42d4bcdb6f58c4209c3490600090a1565b611fed611848565b6001600160a01b0316336001600160a01b03161461203c5760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b6006805460ff19169055604080513381526000602082015281517f532bec1988bda028bb59aba6eb1db09c7209eac3ac08644acb899122b604d1c2929181900390910190a1565b6001600160a01b031660009081526024602052604090205490565b60065460ff1681565b6120af612668565b6120ee576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600780546001600160a01b0319166001600160a01b038316908117909155600d546040519091907faa735ef3e20d6d58610022edb69ae0e7e8aaa0084dc5699a0b36a5683bc7a7c790600090a350565b612146612668565b612185576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b6001600160a01b038116600081815260126020526040808220805460ff19169055514392917fa40f23a963aabba33c55679497d6dd6d9815feadbeb0b0ad39d1285beda16bdd91a350565b60025481565b6001600160a01b03919091166000908152601760209081526040808320938352929052206006015490565b60008281526018602090815260408083206001600160a01b038516845260010190915290205492915050565b612235612668565b612274576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b601181905560405181907f1177d9c2a77eb9dd45c02329c8e4924e44101d64dabf8024543b0ce26e622f3690600090a250565b3360009081526012602052604090205460ff1615156001146122fa5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6001600160a01b03909116600090815260246020526040902055565b600054600160a01b900460ff1615156001146123635760405162461bcd60e51b815260040180806020018281038252602e815260200180614173602e913960400191505060405180910390fd5b600e54612379906201518063ffffffff613c1a16565b4211156124295760006123ad6305f5e1006123a1600d54600154613cdd90919063ffffffff16565b9063ffffffff613d3616565b90506123cf6123ca62015180600e54613c1a90919063ffffffff16565b613d78565b6007546123e5906001600160a01b031682611af0565b6007546040805183815290516001600160a01b03909216917f38fec7f72e65a01ab4170fddd9ed4438b1b378e84bef08292112fb619abfc9a29181900360200190a2505b565b600c546001600160a01b031681565b6001600160a01b031660009081526014602052604090205490565b61245d612668565b61249c576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b600b546001600160a01b031690565b60255490565b6040805160609a909a1b6bffffffffffffffffffffffff19166020808c019190915260348b019990995260548a01979097526074890195909552609488019390935260b487019190915260d486015260f485015261011480850191909152815180850390910181526101349093019052815191012090565b60105481565b60055490565b6040805160609390931b6bffffffffffffffffffffffff19166020808501919091526034808501939093528151808503909301835260549093019052805191012090565b60255481565b6000546001600160a01b031690565b6125e0612668565b61261f576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b6001600160a01b038116600081815260136020526040808220805460ff19169055517f972d3365ef4d458e53aedba4b7422b4eea3046ea55b243b9e64341b1f1ad449d9190a250565b6000546001600160a01b0316331490565b3360009081526012602052604090205460ff1615156001146126cc5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6126d7838383612b20565b6126e2838383611857565b505050565b600e5481565b3360009081526012602052604090205460ff1615156001146127405760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60065460ff16156127825760405162461bcd60e51b815260040180806020018281038252602781526020018061429d6027913960400191505060405180910390fd5b6001600160a01b0382166000908152601460205260409020548111156127ef576040805162461bcd60e51b815260206004820152601f60248201527f4d6f727068657253746174653a204e6f7420656e6f75676820746f6b656e2e00604482015290519081900360640190fd5b6001600160a01b038216600090815260146020526040902054612818908263ffffffff613dab16565b6001600160a01b038316600090815260146020526040902055600254612844908263ffffffff613dab16565b60025561284f613c7b565b600c54604080516323de665160e01b81526001600160a01b0385811660048301526000602483018190526044830186905292519316926323de66519260648084019391929182900301818387803b1580156128a957600080fd5b505af11580156128bd573d6000803e3d6000fd5b505060025460408051858152602081019290925280516001600160a01b03871694507f49995e5dd6158cf69ad3e9777c46755a1a826a446c6416992167462dad033b2a9350918290030190a26001600160a01b038216600090815260146020526040902054611cc290839061257f565b3360009081526012602052604090205460ff1615156001146129805760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60258190556040805182815290517f8347cc6d3a3b991db61121237578d3a133ddf434ee43936f1c48d2c815eb0ab39181900360200190a150565b6129c36124e6565b6001600160a01b0316336001600160a01b031614612a125760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b6000601e8190556040517fcada5cc63a6cd5770ca818284aa0ee429013dfd689c4f9587022943b408a09b19190a1565b612a4a6124e6565b6001600160a01b0316336001600160a01b031614612a995760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b80601e541115612abe57601e54612ab6908263ffffffff613dab16565b601e55612ac4565b6000601e555b42601d819055601e5460408051918252602082019290925281517fa11a2bc3cadf4e1be663d8cd5705d0e1dfab645a6d258fa97b350610640d30a0929181900390910190a150565b60065461010090046001600160a01b031681565b3360009081526012602052604090205460ff161515600114612b735760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60009283526018602090815260408085206001600160a01b03909416855260019093019052912055565b601d5481565b601e5481565b612bb1611848565b6001600160a01b0316336001600160a01b031614612c005760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b600081815260166020526040808220805460ff191660011790555182917f52ebf9d662e8bc70841a5b603c1711882a8e4b11a663af6b5709286fe7bd964591a250565b612c4b612668565b612c8a576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b6001600160a01b038116600081815260136020526040808220805460ff19166001179055517f6d3bdb877ca7bde5be7e4afec9b4afd12e4f3dd1188c8fa57a7802f0f6cfa4d49190a250565b612cde6124e6565b6001600160a01b0316336001600160a01b031614612d2d5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b60208181556040805183815290517faf1ea5ac33bf092763f62a127ef50006ae56eef9cc122568bea97c7308d17376929181900390910190a150565b6000546001600160a01b031681565b612d806124e6565b6001600160a01b0316336001600160a01b031614612dcf5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b6000908152601c60205260409020805460ff19166001179055565b60215481565b600d5481565b612dfe612668565b612e3d576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600c80546001600160a01b0319166001600160a01b0383169081179091556040517f0e6436d2b3e53a8a3ec2fbdd1d22525f0cd81d796bcb4beeef7337031a7e5efa90600090a250565b3360009081526012602052604090205460ff161515600114612eda5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6001600160a01b0316600090815260246020526040902080546001019055565b3360009081526012602052604090205460ff161515600114612f4d5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6001600160a01b03891660009081526017602090815260408083208b845290915290208781556001810187905560028101869055600381018590556004810184905560058101839055600601819055612fad8989898989898989896124fb565b6001600160a01b038a1660009081526017602090815260408083208c845290915290206007015585151580612fe25750600085115b15612ff657612ff1888a613ded565b613000565b613000888a613e2d565b6001600160a01b03891660008181526017602090815260408083208c84528252918290206007015482518b81529182018a9052818301899052606082018890526080820187905260a0820186905260c0820185905291518b9392917f35ea872e77adbec19df83a66765d5bdc0adfe73d9ada9518cb384242ddb40d5d919081900360e00190a4505050505050505050565b3360009081526012602052604090205460ff1615156001146130e45760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60065460ff16156131265760405162461bcd60e51b815260040180806020018281038252602781526020018061429d6027913960400191505060405180910390fd5b6001600160a01b038316600090815260146020526040902054811115613193576040805162461bcd60e51b815260206004820152601f60248201527f4d6f727068657253746174653a204e6f7420656e6f75676820746f6b656e2e00604482015290519081900360640190fd5b6001600160a01b0383166000908152601460205260409020546131bc908263ffffffff613dab16565b6001600160a01b0380851660009081526014602052604080822093909355908416815220546131f1908263ffffffff613c1a16565b6001600160a01b0380841660008181526014602052604080822094909455600c5484516323de665160e01b81528885166004820152602481019390935260448301869052935193909216926323de66519260648084019391929182900301818387803b15801561326057600080fd5b505af1158015613274573d6000803e3d6000fd5b50506040805184815290516001600160a01b038087169450871692507fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a36001600160a01b0383166000908152601460205260409020546132de90849061257f565b6001600160a01b03841660008181526014602090815260409182902054825190815291517fd5cc1526bf6f20f18608ca8834d23bacab6780c93fa2e5e7033a5c85016af0469281900390910190a36001600160a01b03821660009081526014602052604090205461335090839061257f565b6001600160a01b03831660008181526014602090815260409182902054825190815291517fd5cc1526bf6f20f18608ca8834d23bacab6780c93fa2e5e7033a5c85016af0469281900390910190a3505050565b6009546001600160a01b031681565b600054600160a01b900460ff1681565b6001600160a01b031660009081526023602052604090205490565b600a546001600160a01b031633146134265760405162461bcd60e51b815260040180806020018281038252603d8152602001806141ea603d913960400191505060405180910390fd5b6004819055613433613c7b565b6040805182815290517f38e3203d00fb51f959df7882c56c583370da2f7abea215c09e83e7ffa61281d29181900360200190a150565b613471612668565b6134b0576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600b80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f631bdf9495e4e83ab921eecb28e1057d3598a3fa0fc5f40b06bafe3e7333bc5c9181900360200190a150565b60205481565b6135126124e6565b6001600160a01b0316336001600160a01b0316146135615760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b601e54613574908263ffffffff613c1a16565b601e819055601d5460408051928352602083019190915280517fa11a2bc3cadf4e1be663d8cd5705d0e1dfab645a6d258fa97b350610640d30a09281900390910190a150565b6135c2611848565b6001600160a01b0316336001600160a01b0316146136115760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b6006805460ff1916600190811790915560408051338152602081019290925280517f532bec1988bda028bb59aba6eb1db09c7209eac3ac08644acb899122b604d1c29281900390910190a1565b60225460ff1681565b3360009081526012602052604090205460ff1615156001146136ba5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6001600160a01b03808416600081815260156020908152604080832094871680845294825291829020859055815185815291517f3c07380f6fcae3bac39771c60e5c680334073911f2176b65f1d6925ba0badcdf9281900390910190a3505050565b613724611848565b6001600160a01b0316336001600160a01b0316146137735760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b6305f5e10081116137b55760405162461bcd60e51b81526004018080602001828103825260278152602001806141076027913960400191505060405180910390fd5b60058190556040805182815290517f258a1584bca0aad852538c9d396233520174feedba906a03d19b307d3bad5f309181900360200190a150565b60006137fa612668565b613839576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b826001600160a01b031663a9059cbb6138506125c9565b846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b1580156138a057600080fd5b505af11580156138b4573d6000803e3d6000fd5b505050506040513d60208110156138ca57600080fd5b50519392505050565b6138db6119aa565b6001600160a01b0316336001600160a01b03161461392a5760405162461bcd60e51b815260040180806020018281038252604581526020018061412e6045913960600191505060405180910390fd5b600880546001600160a01b0319166001600160a01b0383169081179091556040517f47c6cd80582c55aabfec5a8be39d30b380cf41ba92dd2d13ba626c48c96bf27690600090a250565b6001600160a01b03919091166000908152601760209081526040808320938352929052206003015490565b6009546001600160a01b031690565b600b546001600160a01b031681565b60105490565b6139cb611848565b6001600160a01b0316336001600160a01b031614613a1a5760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b6003819055613a27613c7b565b6040805182815290517ff915189a6212c055e85c9c0dc760b7a2a5d1ff9a9e64bd9af0a9897b4046dcd99181900360200190a150565b6001600160a01b03166000908152601b602052604090205490565b6001600160a01b03919091166000908152601760209081526040808320938352929052206001015490565b60009081526018602052604090205490565b6001600160a01b03919091166000908152601760209081526040808320938352929052206004015490565b613ae8612668565b613b27576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b613b3081613eb9565b50565b6008546001600160a01b031681565b6007546001600160a01b031681565b6001600160a01b03919091166000908152601760209081526040808320938352929052206005015490565b600f5481565b613b8a6124e6565b6001600160a01b0316336001600160a01b031614613bd95760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b601f8190556040805182815290517f0969f79b044617688492c7c9b226129947037ca88c450002a7561ed78aa549ac9181900360200190a150565b60115490565b600082820183811015613c74576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b613ca4600454613c98600354600254613c1a90919063ffffffff16565b9063ffffffff613c1a16565b600181905560408051918252517f5b1767df4e2cc8a7b2716959e609e0cdd987c9b88ac27b7fc4be99435aa1673b9181900360200190a1565b600082613cec5750600061167a565b82820282848281613cf957fe5b0414613c745760405162461bcd60e51b81526004018080602001828103825260218152602001806141c96021913960400191505060405180910390fd5b6000613c7483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613f59565b600e81905560405181907fb11f7283fda904f54a0fc8af727d3bf56e40a6cbf7c8fbb177083f0a335152ed90600090a250565b6000613c7483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613ffb565b6000613df98383612201565b9050806126e2576000613e106001613c9886613aa3565b9050613e1c8482611924565b613e27848483612679565b50505050565b6000613e398383612201565b90506000613e4684613aa3565b90506000613e5485836119cd565b90508215613eb25781831015613e7a57613e6f858285611857565b613e7a858285612b20565b613e8685600084611857565b613e9285856000612b20565b8115613eb257613eb285613ead84600163ffffffff613dab16565b611924565b5050505050565b6001600160a01b038116613efe5760405162461bcd60e51b81526004018080602001828103825260288152602001806141a16028913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60008183613fe55760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613faa578181015183820152602001613f92565b50505050905090810190601f168015613fd75780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581613ff157fe5b0495945050505050565b6000818484111561404d5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315613faa578181015183820152602001613f92565b50505090039056fe4d6f727068657253746174653a2043616c6c6572206973206e6f7420746865204272696467652e2041626f7274696e672e4d6f727068657253746174653a2052657761726420626173697320706f696e7473206e65656420746f206265206c657373206f7220657175616c20746f2031353030302e4d6f727068657253746174653a204f6e6c7920506c6174666f726d20697320616c6c6f77656420746f2065786563757465206f7065726174696f6e2e4d6f727068657253746174653a204c6576657261676520707265636973696f6e206973203165384d6f727068657253746174653a2043616c6c696e6720636f6e7472616374206e6f742074686520476f7665726e616e636520436f6e74726163742e2041626f7274696e672e4d6f727068657253746174653a2043616e206f6e6c792062652063616c6c6564206f6e206d61696e636861696e2e4f776e61626c653a207573652072656e6f756e6365206f776e65727368697020696e73746561642e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774d6f727068657253746174653a2043616c6c6572206973206e6f74207468652053696465636861696e204f70657261746f722e2041626f7274696e672e4d6f727068657253746174653a2052657761726420626173697320706f696e74732063616e206f6e6c7920626520736574206f6e20457468657265756d2e4d6f727068657253746174653a2043616c6c6572206973206e6f74207468652041646d696e6973747261746f722e2041626f7274696e672e4d6f727068657253746174653a20436f6e7472616374207061757365642c2061626f7274696e674f776e61626c653a2063616c6c65722073686f756c64206265206f776e65722ea265627a7a72315820160459360f99868cb32b4e506044eeea98d9c28ae8691a9461867be3f47ceaa764736f6c634300051000324d6f727068657253746174653a2052657761726420626173697320706f696e7473206e65656420746f206265206c657373206f7220657175616c20746f2031353030302e4d6f727068657253746174653a204f6e6c7920506c6174666f726d20697320616c6c6f77656420746f2065786563757465206f7065726174696f6e2e4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f4d6f727068657253746174653a2043616c6c6572206973206e6f74207468652053696465636861696e204f70657261746f722e2041626f7274696e672e4d6f727068657253746174653a2052657761726420626173697320706f696e74732063616e206f6e6c7920626520736574206f6e20457468657265756d2e4f776e61626c653a2063616c6c65722073686f756c64206265206f776e65722e000000000000000000000000000000000000000000000000000000000000000100000000000000000000000070dcdb66e128738189012dee12d7e13b377a1d3b000000000000000000000000e261d68bda5bd518598e31320ede6e1e2d53682f

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106106e05760003560e01c80637c995e9111610387578063bfde5730116101de578063e4974f8d1161010f578063f2fde38b116100ad578063faddee1411610087578063faddee1414611292578063fbfc50f6146112be578063fc89a4fc146112c6578063ff047c38146112e3576106e0565b8063f2fde38b1461125c578063f53d0a8e14611282578063f606a41a1461128a576106e0565b8063ebd164fb116100e9578063ebd164fb146111c1578063ef5fa322146111e7578063ef92f83114611213578063efeecb0414611230576106e0565b8063e4974f8d14611194578063e4bd85221461119c578063e5160f80146111a4576106e0565b8063d8d5470d1161017c578063dc39d06d11610156578063dc39d06d1461110e578063df8089ef1461113a578063e291f13514611160578063e3bbb5651461118c576106e0565b8063d8d5470d146110b3578063da46098c146110bb578063da4b0f40146110f1576106e0565b8063c5e1b59a116101b8578063c5e1b59a14611060578063d362bd2b14611086578063d69082c41461108e578063d7118351146110ab576106e0565b8063bfde573014611015578063c209afac1461101d578063c5d90a1914611043576106e0565b8063aa43ced8116102b8578063b8ed12a411610256578063bcc3e34211610230578063bcc3e34214610f59578063be7e64b614610f7f578063beabacc814610fd7578063bece75321461100d576106e0565b8063b8ed12a414610f23578063bb65b24214610f2b578063bbcd5bbe14610f33576106e0565b8063acb17ba711610292578063acb17ba714610ebb578063af434a6d14610ee1578063b2bdfa7b14610efe578063b6554c2c14610f06576106e0565b8063aa43ced814610e8e578063aa7bcd5d14610e96578063ac981b1e14610e9e576106e0565b80639231cf7411610325578063a0580880116102ff578063a058088014610e2f578063a35ab9c814610e37578063a8c8afaa14610e54578063a99d389f14610e5c576106e0565b80639231cf7414610dde5780639dc29fac14610de65780639fe4e9d214610e12576106e0565b80638da5cb5b116103615780638da5cb5b14610d765780638ea09da614610d7e5780638f32d59b14610da45780639162298f14610dac576106e0565b80637c995e9114610d3a578063857b0da014610d425780638c4050b114610d6e576106e0565b80633d7f4f3c1161053b57806361afd5ac1161046c578063706277da1161040a57806373ed1fe2116103e457806373ed1fe214610cca578063755ca87a14610cd25780637a68744414610cda5780637b431ab114610d32576106e0565b8063706277da14610c9457806370a0823114610c9c578063715018a614610cc2576106e0565b806369c66c7b1161044657806369c66c7b14610c1757806369cdcfb714610c435780636c36a4ec14610c605780636d37e21814610c8c576106e0565b806361afd5ac14610bbd578063626be56714610be3578063652f176314610beb576106e0565b80634da3c199116104d95780635996e209116104b35780635996e20914610b615780635c8b933414610b695780635c975abb14610b8f5780635e00e67914610b97576106e0565b80634da3c19914610b3457806355b3374114610b51578063592b6aab14610b59576106e0565b8063422cc2e711610515578063422cc2e714610aa857806344ae029c14610ad4578063496ccd9b14610af15780634a4cce9714610b17576106e0565b80633d7f4f3c14610a485780633eedf76a14610a7457806340c10f1914610a7c576106e0565b8063169674071161061557806321c02c8e116105b357806328b7bede1161058d57806328b7bede146109cb5780632d7b42c1146109d35780633383e8d8146109f6578063364ae26e14610a22576106e0565b806321c02c8e1461099557806325fbf712146109bb578063289b3c0d146109c3576106e0565b80631864ba30116105ef5780631864ba30146109365780631bdbae90146109625780631cb110771461096a5780632020e69714610972576106e0565b806316967407146108f4578063174c51dc146108fc57806318160ddd1461092e576106e0565b80630b7c8e7f116106825780630fa8f5161161065c5780630fa8f516146108235780631129753f1461088257806314712512146108a857806314ce70ef146108ce576106e0565b80630b7c8e7f146107d95780630eb933dc146107e15780630f508e001461081b576106e0565b806309089f97116106be57806309089f97146107475780630aa7cee2146107615780630ae5e739146107855780630af4187d146107ab576106e0565b806304371f48146106e557806306442d0a1461070457806307a9100e14610721575b600080fd5b610702600480360360208110156106fb57600080fd5b50356112eb565b005b6107026004803603602081101561071a57600080fd5b503561140c565b6107026004803603602081101561073757600080fd5b50356001600160a01b03166114a3565b61074f611512565b60408051918252519081900360200190f35b6107696115af565b604080516001600160a01b039092168252519081900360200190f35b6107026004803603602081101561079b57600080fd5b50356001600160a01b03166115be565b61074f600480360360408110156107c157600080fd5b506001600160a01b0381358116916020013516611653565b61074f611680565b610807600480360360208110156107f757600080fd5b50356001600160a01b0316611686565b604080519115158252519081900360200190f35b6107696116a4565b61084f6004803603604081101561083957600080fd5b506001600160a01b0381351690602001356116b3565b604080519687526020870195909552858501939093526060850191909152608084015260a0830152519081900360c00190f35b6107026004803603602081101561089857600080fd5b50356001600160a01b0316611700565b610807600480360360208110156108be57600080fd5b50356001600160a01b0316611799565b610702600480360360208110156108e457600080fd5b50356001600160a01b03166117b7565b610769611848565b6107026004803603606081101561091257600080fd5b508035906001600160a01b036020820135169060400135611857565b61074f6118e7565b61074f6004803603604081101561094c57600080fd5b506001600160a01b0381351690602001356118ed565b61074f611918565b61074f61191e565b6107026004803603604081101561098857600080fd5b5080359060200135611924565b61074f600480360360208110156109ab57600080fd5b50356001600160a01b0316611989565b61074f6119a4565b6107696119aa565b6107696119be565b610769600480360360408110156109e957600080fd5b50803590602001356119cd565b61070260048036036040811015610a0c57600080fd5b506001600160a01b0381351690602001356119f7565b61074f60048036036020811015610a3857600080fd5b50356001600160a01b0316611aa7565b61074f60048036036040811015610a5e57600080fd5b506001600160a01b038135169060200135611ac2565b61074f611aea565b61070260048036036040811015610a9257600080fd5b506001600160a01b038135169060200135611af0565b61070260048036036040811015610abe57600080fd5b506001600160a01b038135169060200135611d14565b61080760048036036020811015610aea57600080fd5b5035611dfa565b61070260048036036020811015610b0757600080fd5b50356001600160a01b0316611e0f565b61080760048036036020811015610b2d57600080fd5b5035611eb0565b61070260048036036020811015610b4a57600080fd5b5035611ec5565b61074f611f53565b610702611f59565b610702611fe5565b61074f60048036036020811015610b7f57600080fd5b50356001600160a01b0316612083565b61080761209e565b61070260048036036020811015610bad57600080fd5b50356001600160a01b03166120a7565b61070260048036036020811015610bd357600080fd5b50356001600160a01b031661213e565b61074f6121d0565b61074f60048036036040811015610c0157600080fd5b506001600160a01b0381351690602001356121d6565b61074f60048036036040811015610c2d57600080fd5b50803590602001356001600160a01b0316612201565b61070260048036036020811015610c5957600080fd5b503561222d565b61070260048036036040811015610c7657600080fd5b506001600160a01b0381351690602001356122a7565b610702612316565b61076961242b565b61074f60048036036020811015610cb257600080fd5b50356001600160a01b031661243a565b610702612455565b6107696124e6565b61074f6124f5565b61074f6004803603610120811015610cf157600080fd5b506001600160a01b038135169060208101359060408101359060608101359060808101359060a08101359060c08101359060e08101359061010001356124fb565b61074f612573565b61074f612579565b61074f60048036036040811015610d5857600080fd5b506001600160a01b03813516906020013561257f565b61074f6125c3565b6107696125c9565b61070260048036036020811015610d9457600080fd5b50356001600160a01b03166125d8565b610807612668565b61070260048036036060811015610dc257600080fd5b508035906001600160a01b036020820135169060400135612679565b61074f6126e7565b61070260048036036040811015610dfc57600080fd5b506001600160a01b0381351690602001356126ed565b61070260048036036020811015610e2857600080fd5b503561292d565b6107026129bb565b61070260048036036020811015610e4d57600080fd5b5035612a42565b610769612b0c565b61070260048036036060811015610e7257600080fd5b508035906001600160a01b036020820135169060400135612b20565b61074f612b9d565b61074f612ba3565b61070260048036036020811015610eb457600080fd5b5035612ba9565b61070260048036036020811015610ed157600080fd5b50356001600160a01b0316612c43565b61070260048036036020811015610ef757600080fd5b5035612cd6565b610769612d69565b61070260048036036020811015610f1c57600080fd5b5035612d78565b61074f612dea565b61074f612df0565b61070260048036036020811015610f4957600080fd5b50356001600160a01b0316612df6565b61070260048036036020811015610f6f57600080fd5b50356001600160a01b0316612e87565b6107026004803603610120811015610f9657600080fd5b506001600160a01b038135169060208101359060408101359060608101359060808101359060a08101359060c08101359060e0810135906101000135612efa565b61070260048036036060811015610fed57600080fd5b506001600160a01b03813581169160208101359091169060400135613091565b6107696133a3565b6108076133b2565b61074f6004803603602081101561103357600080fd5b50356001600160a01b03166133c2565b6107026004803603602081101561105957600080fd5b50356133dd565b6107026004803603602081101561107657600080fd5b50356001600160a01b0316613469565b61074f613504565b610702600480360360208110156110a457600080fd5b503561350a565b6107026135ba565b61080761365e565b610702600480360360608110156110d157600080fd5b506001600160a01b03813581169160208101359091169060400135613667565b6107026004803603602081101561110757600080fd5b503561371c565b6108076004803603604081101561112457600080fd5b506001600160a01b0381351690602001356137f0565b6107026004803603602081101561115057600080fd5b50356001600160a01b03166138d3565b61074f6004803603604081101561117657600080fd5b506001600160a01b038135169060200135613974565b61076961399f565b6107696139ae565b61074f6139bd565b610702600480360360208110156111ba57600080fd5b50356139c3565b61074f600480360360208110156111d757600080fd5b50356001600160a01b0316613a5d565b61074f600480360360408110156111fd57600080fd5b506001600160a01b038135169060200135613a78565b61074f6004803603602081101561122957600080fd5b5035613aa3565b61074f6004803603604081101561124657600080fd5b506001600160a01b038135169060200135613ab5565b6107026004803603602081101561127257600080fd5b50356001600160a01b0316613ae0565b610769613b33565b610769613b42565b61074f600480360360408110156112a857600080fd5b506001600160a01b038135169060200135613b51565b61074f613b7c565b610702600480360360208110156112dc57600080fd5b5035613b82565b61074f613c14565b6112f3612668565b611332576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600054600160a01b900460ff1615156001141561138f57613a9881111561138a5760405162461bcd60e51b81526004018080602001828103825260448152602001806140876044913960600191505060405180910390fd5b6113cc565b80156113cc5760405162461bcd60e51b815260040180806020018281038252603e815260200180614227603e913960400191505060405180910390fd5b600d81905560075460405182916001600160a01b0316907faa735ef3e20d6d58610022edb69ae0e7e8aaa0084dc5699a0b36a5683bc7a7c790600090a350565b611414611848565b6001600160a01b0316336001600160a01b0316146114635760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b600081815260166020526040808220805460ff191690555182917f9cb9d54a58b209894faa9f115e54b1c61733c0764fe29ed01f97c7c425f2f24391a250565b3360009081526012602052604090205460ff1615156001146114f65760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6001600160a01b03166000908152602360205260409020439055565b600061151c6124e6565b6001600160a01b0316336001600160a01b03161461156b5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b602180546001019081905560408051918252517f86423ef8971dc4252acb273ac1099fb639020a7a2f5a64dad077d033ab2ae8e29181900360200190a15060215490565b600a546001600160a01b031681565b6115c6612668565b611605576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b6001600160a01b038116600081815260126020526040808220805460ff19166001179055514392917f556646edb498605e1eaf0f4ab1619f3dbc4164f1cddc22ecae584e045838d13891a350565b6001600160a01b038083166000908152601560209081526040808320938516835292905220545b92915050565b60035481565b6001600160a01b031660009081526013602052604090205460ff1690565b600a546001600160a01b031690565b6001600160a01b0391909116600090815260176020908152604080832093835292905220600181015460028201546003830154600484015460058501546006909501549395929491939092565b611708612668565b611747576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b60068054610100600160a81b0319166101006001600160a01b038416908102919091179091556040517f5ab1e8b2c0a96bffa69cb323894590e00556bdce76b87d529100949740e6a55a90600090a250565b6001600160a01b031660009081526012602052604090205460ff1690565b6117bf612668565b6117fe576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600a80546001600160a01b0319166001600160a01b0383169081179091556040517f07c5be40db03f5890f6ca87fc24a286cabbbd63a79791089701cb0b5eb71529890600090a250565b6008546001600160a01b031690565b3360009081526012602052604090205460ff1615156001146118aa5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60009283526018602090815260408085209285526002909201905290912080546001600160a01b0319166001600160a01b03909216919091179055565b60015481565b6001600160a01b03919091166000908152601760209081526040808320938352929052206002015490565b60045481565b601f5481565b3360009081526012602052604090205460ff1615156001146119775760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60009182526018602052604090912055565b6001600160a01b031660009081526019602052604090205490565b600f5490565b60065461010090046001600160a01b031690565b600c546001600160a01b031690565b6000918252601860209081526040808420928452600290920190529020546001600160a01b031690565b6119ff6124e6565b6001600160a01b0316336001600160a01b031614611a4e5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b6001600160a01b0382166000818152601960209081526040918290208490558151928352820183905280517fb83fc1206022cf828cdd927bea92f3cfe9ae485bc4d4308b65413dfdd0ab6edb9281900390910190a15050565b6001600160a01b03166000908152601a602052604090205490565b6001600160a01b03919091166000908152601760209081526040808320938352929052205490565b60055481565b3360009081526012602052604090205460ff161515600114611b435760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60065460ff1615611b855760405162461bcd60e51b815260040180806020018281038252602781526020018061429d6027913960400191505060405180910390fd5b6001600160a01b038216600090815260146020526040902054611bae908263ffffffff613c1a16565b6001600160a01b038316600090815260146020526040902055600254611bda908263ffffffff613c1a16565b600255611be5613c7b565b600c54604080516323de665160e01b81526000600482018190526001600160a01b03868116602484015260448301869052925192909316926323de66519260648084019382900301818387803b158015611c3e57600080fd5b505af1158015611c52573d6000803e3d6000fd5b505060025460408051858152602081019290925280516001600160a01b03871694507f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f9350918290030190a26001600160a01b038216600090815260146020526040902054611cc290839061257f565b6001600160a01b03831660008181526014602090815260409182902054825190815291517fd5cc1526bf6f20f18608ca8834d23bacab6780c93fa2e5e7033a5c85016af0469281900390910190a35050565b611d1c6124e6565b6001600160a01b0316336001600160a01b031614611d6b5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b6001600160a01b0382166000908152601a60208181526040808420858155601b835293204290555254611d9f90839061257f565b6001600160a01b0383166000818152601a602090815260409182902054825193845290830185905282820152517fa3579111956ed8ebf7836e375375f707ea762883fa60008df45a289d53090b659181900360600190a25050565b6000908152601c602052604090205460ff1690565b611e176119aa565b6001600160a01b0316336001600160a01b031614611e665760405162461bcd60e51b815260040180806020018281038252604581526020018061412e6045913960600191505060405180910390fd5b600980546001600160a01b0319166001600160a01b0383169081179091556040517f127863dda9b4c03043886af0affd8e8ff8c0c65822d70f0b639eadce57271f0890600090a250565b60009081526016602052604090205460ff1690565b611ecd6124e6565b6001600160a01b0316336001600160a01b031614611f1c5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b600f8190554260105560405181907f2fe11f024562cd0798f5b3975c7be128c3b86e0249f9a66ad1e74bfb52f9246490600090a250565b60115481565b611f616124e6565b6001600160a01b0316336001600160a01b031614611fb05760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b6022805460ff191690556040517ff6b2b9c63998bbfbe0a548dce3fa97702cb864dbfbdb42d4bcdb6f58c4209c3490600090a1565b611fed611848565b6001600160a01b0316336001600160a01b03161461203c5760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b6006805460ff19169055604080513381526000602082015281517f532bec1988bda028bb59aba6eb1db09c7209eac3ac08644acb899122b604d1c2929181900390910190a1565b6001600160a01b031660009081526024602052604090205490565b60065460ff1681565b6120af612668565b6120ee576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600780546001600160a01b0319166001600160a01b038316908117909155600d546040519091907faa735ef3e20d6d58610022edb69ae0e7e8aaa0084dc5699a0b36a5683bc7a7c790600090a350565b612146612668565b612185576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b6001600160a01b038116600081815260126020526040808220805460ff19169055514392917fa40f23a963aabba33c55679497d6dd6d9815feadbeb0b0ad39d1285beda16bdd91a350565b60025481565b6001600160a01b03919091166000908152601760209081526040808320938352929052206006015490565b60008281526018602090815260408083206001600160a01b038516845260010190915290205492915050565b612235612668565b612274576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b601181905560405181907f1177d9c2a77eb9dd45c02329c8e4924e44101d64dabf8024543b0ce26e622f3690600090a250565b3360009081526012602052604090205460ff1615156001146122fa5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6001600160a01b03909116600090815260246020526040902055565b600054600160a01b900460ff1615156001146123635760405162461bcd60e51b815260040180806020018281038252602e815260200180614173602e913960400191505060405180910390fd5b600e54612379906201518063ffffffff613c1a16565b4211156124295760006123ad6305f5e1006123a1600d54600154613cdd90919063ffffffff16565b9063ffffffff613d3616565b90506123cf6123ca62015180600e54613c1a90919063ffffffff16565b613d78565b6007546123e5906001600160a01b031682611af0565b6007546040805183815290516001600160a01b03909216917f38fec7f72e65a01ab4170fddd9ed4438b1b378e84bef08292112fb619abfc9a29181900360200190a2505b565b600c546001600160a01b031681565b6001600160a01b031660009081526014602052604090205490565b61245d612668565b61249c576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b600b546001600160a01b031690565b60255490565b6040805160609a909a1b6bffffffffffffffffffffffff19166020808c019190915260348b019990995260548a01979097526074890195909552609488019390935260b487019190915260d486015260f485015261011480850191909152815180850390910181526101349093019052815191012090565b60105481565b60055490565b6040805160609390931b6bffffffffffffffffffffffff19166020808501919091526034808501939093528151808503909301835260549093019052805191012090565b60255481565b6000546001600160a01b031690565b6125e0612668565b61261f576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b6001600160a01b038116600081815260136020526040808220805460ff19169055517f972d3365ef4d458e53aedba4b7422b4eea3046ea55b243b9e64341b1f1ad449d9190a250565b6000546001600160a01b0316331490565b3360009081526012602052604090205460ff1615156001146126cc5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6126d7838383612b20565b6126e2838383611857565b505050565b600e5481565b3360009081526012602052604090205460ff1615156001146127405760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60065460ff16156127825760405162461bcd60e51b815260040180806020018281038252602781526020018061429d6027913960400191505060405180910390fd5b6001600160a01b0382166000908152601460205260409020548111156127ef576040805162461bcd60e51b815260206004820152601f60248201527f4d6f727068657253746174653a204e6f7420656e6f75676820746f6b656e2e00604482015290519081900360640190fd5b6001600160a01b038216600090815260146020526040902054612818908263ffffffff613dab16565b6001600160a01b038316600090815260146020526040902055600254612844908263ffffffff613dab16565b60025561284f613c7b565b600c54604080516323de665160e01b81526001600160a01b0385811660048301526000602483018190526044830186905292519316926323de66519260648084019391929182900301818387803b1580156128a957600080fd5b505af11580156128bd573d6000803e3d6000fd5b505060025460408051858152602081019290925280516001600160a01b03871694507f49995e5dd6158cf69ad3e9777c46755a1a826a446c6416992167462dad033b2a9350918290030190a26001600160a01b038216600090815260146020526040902054611cc290839061257f565b3360009081526012602052604090205460ff1615156001146129805760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60258190556040805182815290517f8347cc6d3a3b991db61121237578d3a133ddf434ee43936f1c48d2c815eb0ab39181900360200190a150565b6129c36124e6565b6001600160a01b0316336001600160a01b031614612a125760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b6000601e8190556040517fcada5cc63a6cd5770ca818284aa0ee429013dfd689c4f9587022943b408a09b19190a1565b612a4a6124e6565b6001600160a01b0316336001600160a01b031614612a995760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b80601e541115612abe57601e54612ab6908263ffffffff613dab16565b601e55612ac4565b6000601e555b42601d819055601e5460408051918252602082019290925281517fa11a2bc3cadf4e1be663d8cd5705d0e1dfab645a6d258fa97b350610640d30a0929181900390910190a150565b60065461010090046001600160a01b031681565b3360009081526012602052604090205460ff161515600114612b735760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60009283526018602090815260408085206001600160a01b03909416855260019093019052912055565b601d5481565b601e5481565b612bb1611848565b6001600160a01b0316336001600160a01b031614612c005760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b600081815260166020526040808220805460ff191660011790555182917f52ebf9d662e8bc70841a5b603c1711882a8e4b11a663af6b5709286fe7bd964591a250565b612c4b612668565b612c8a576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b6001600160a01b038116600081815260136020526040808220805460ff19166001179055517f6d3bdb877ca7bde5be7e4afec9b4afd12e4f3dd1188c8fa57a7802f0f6cfa4d49190a250565b612cde6124e6565b6001600160a01b0316336001600160a01b031614612d2d5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b60208181556040805183815290517faf1ea5ac33bf092763f62a127ef50006ae56eef9cc122568bea97c7308d17376929181900390910190a150565b6000546001600160a01b031681565b612d806124e6565b6001600160a01b0316336001600160a01b031614612dcf5760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b6000908152601c60205260409020805460ff19166001179055565b60215481565b600d5481565b612dfe612668565b612e3d576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600c80546001600160a01b0319166001600160a01b0383169081179091556040517f0e6436d2b3e53a8a3ec2fbdd1d22525f0cd81d796bcb4beeef7337031a7e5efa90600090a250565b3360009081526012602052604090205460ff161515600114612eda5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6001600160a01b0316600090815260246020526040902080546001019055565b3360009081526012602052604090205460ff161515600114612f4d5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6001600160a01b03891660009081526017602090815260408083208b845290915290208781556001810187905560028101869055600381018590556004810184905560058101839055600601819055612fad8989898989898989896124fb565b6001600160a01b038a1660009081526017602090815260408083208c845290915290206007015585151580612fe25750600085115b15612ff657612ff1888a613ded565b613000565b613000888a613e2d565b6001600160a01b03891660008181526017602090815260408083208c84528252918290206007015482518b81529182018a9052818301899052606082018890526080820187905260a0820186905260c0820185905291518b9392917f35ea872e77adbec19df83a66765d5bdc0adfe73d9ada9518cb384242ddb40d5d919081900360e00190a4505050505050505050565b3360009081526012602052604090205460ff1615156001146130e45760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b60065460ff16156131265760405162461bcd60e51b815260040180806020018281038252602781526020018061429d6027913960400191505060405180910390fd5b6001600160a01b038316600090815260146020526040902054811115613193576040805162461bcd60e51b815260206004820152601f60248201527f4d6f727068657253746174653a204e6f7420656e6f75676820746f6b656e2e00604482015290519081900360640190fd5b6001600160a01b0383166000908152601460205260409020546131bc908263ffffffff613dab16565b6001600160a01b0380851660009081526014602052604080822093909355908416815220546131f1908263ffffffff613c1a16565b6001600160a01b0380841660008181526014602052604080822094909455600c5484516323de665160e01b81528885166004820152602481019390935260448301869052935193909216926323de66519260648084019391929182900301818387803b15801561326057600080fd5b505af1158015613274573d6000803e3d6000fd5b50506040805184815290516001600160a01b038087169450871692507fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a36001600160a01b0383166000908152601460205260409020546132de90849061257f565b6001600160a01b03841660008181526014602090815260409182902054825190815291517fd5cc1526bf6f20f18608ca8834d23bacab6780c93fa2e5e7033a5c85016af0469281900390910190a36001600160a01b03821660009081526014602052604090205461335090839061257f565b6001600160a01b03831660008181526014602090815260409182902054825190815291517fd5cc1526bf6f20f18608ca8834d23bacab6780c93fa2e5e7033a5c85016af0469281900390910190a3505050565b6009546001600160a01b031681565b600054600160a01b900460ff1681565b6001600160a01b031660009081526023602052604090205490565b600a546001600160a01b031633146134265760405162461bcd60e51b815260040180806020018281038252603d8152602001806141ea603d913960400191505060405180910390fd5b6004819055613433613c7b565b6040805182815290517f38e3203d00fb51f959df7882c56c583370da2f7abea215c09e83e7ffa61281d29181900360200190a150565b613471612668565b6134b0576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b600b80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f631bdf9495e4e83ab921eecb28e1057d3598a3fa0fc5f40b06bafe3e7333bc5c9181900360200190a150565b60205481565b6135126124e6565b6001600160a01b0316336001600160a01b0316146135615760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b601e54613574908263ffffffff613c1a16565b601e819055601d5460408051928352602083019190915280517fa11a2bc3cadf4e1be663d8cd5705d0e1dfab645a6d258fa97b350610640d30a09281900390910190a150565b6135c2611848565b6001600160a01b0316336001600160a01b0316146136115760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b6006805460ff1916600190811790915560408051338152602081019290925280517f532bec1988bda028bb59aba6eb1db09c7209eac3ac08644acb899122b604d1c29281900390910190a1565b60225460ff1681565b3360009081526012602052604090205460ff1615156001146136ba5760405162461bcd60e51b815260040180806020018281038252603c8152602001806140cb603c913960400191505060405180910390fd5b6001600160a01b03808416600081815260156020908152604080832094871680845294825291829020859055815185815291517f3c07380f6fcae3bac39771c60e5c680334073911f2176b65f1d6925ba0badcdf9281900390910190a3505050565b613724611848565b6001600160a01b0316336001600160a01b0316146137735760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b6305f5e10081116137b55760405162461bcd60e51b81526004018080602001828103825260278152602001806141076027913960400191505060405180910390fd5b60058190556040805182815290517f258a1584bca0aad852538c9d396233520174feedba906a03d19b307d3bad5f309181900360200190a150565b60006137fa612668565b613839576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b826001600160a01b031663a9059cbb6138506125c9565b846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b1580156138a057600080fd5b505af11580156138b4573d6000803e3d6000fd5b505050506040513d60208110156138ca57600080fd5b50519392505050565b6138db6119aa565b6001600160a01b0316336001600160a01b03161461392a5760405162461bcd60e51b815260040180806020018281038252604581526020018061412e6045913960600191505060405180910390fd5b600880546001600160a01b0319166001600160a01b0383169081179091556040517f47c6cd80582c55aabfec5a8be39d30b380cf41ba92dd2d13ba626c48c96bf27690600090a250565b6001600160a01b03919091166000908152601760209081526040808320938352929052206003015490565b6009546001600160a01b031690565b600b546001600160a01b031681565b60105490565b6139cb611848565b6001600160a01b0316336001600160a01b031614613a1a5760405162461bcd60e51b81526004018080602001828103825260388152602001806142656038913960400191505060405180910390fd5b6003819055613a27613c7b565b6040805182815290517ff915189a6212c055e85c9c0dc760b7a2a5d1ff9a9e64bd9af0a9897b4046dcd99181900360200190a150565b6001600160a01b03166000908152601b602052604090205490565b6001600160a01b03919091166000908152601760209081526040808320938352929052206001015490565b60009081526018602052604090205490565b6001600160a01b03919091166000908152601760209081526040808320938352929052206004015490565b613ae8612668565b613b27576040805162461bcd60e51b815260206004820181905260248201526000805160206142c4833981519152604482015290519081900360640190fd5b613b3081613eb9565b50565b6008546001600160a01b031681565b6007546001600160a01b031681565b6001600160a01b03919091166000908152601760209081526040808320938352929052206005015490565b600f5481565b613b8a6124e6565b6001600160a01b0316336001600160a01b031614613bd95760405162461bcd60e51b81526004018080602001828103825260318152602001806140566031913960400191505060405180910390fd5b601f8190556040805182815290517f0969f79b044617688492c7c9b226129947037ca88c450002a7561ed78aa549ac9181900360200190a150565b60115490565b600082820183811015613c74576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b613ca4600454613c98600354600254613c1a90919063ffffffff16565b9063ffffffff613c1a16565b600181905560408051918252517f5b1767df4e2cc8a7b2716959e609e0cdd987c9b88ac27b7fc4be99435aa1673b9181900360200190a1565b600082613cec5750600061167a565b82820282848281613cf957fe5b0414613c745760405162461bcd60e51b81526004018080602001828103825260218152602001806141c96021913960400191505060405180910390fd5b6000613c7483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613f59565b600e81905560405181907fb11f7283fda904f54a0fc8af727d3bf56e40a6cbf7c8fbb177083f0a335152ed90600090a250565b6000613c7483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613ffb565b6000613df98383612201565b9050806126e2576000613e106001613c9886613aa3565b9050613e1c8482611924565b613e27848483612679565b50505050565b6000613e398383612201565b90506000613e4684613aa3565b90506000613e5485836119cd565b90508215613eb25781831015613e7a57613e6f858285611857565b613e7a858285612b20565b613e8685600084611857565b613e9285856000612b20565b8115613eb257613eb285613ead84600163ffffffff613dab16565b611924565b5050505050565b6001600160a01b038116613efe5760405162461bcd60e51b81526004018080602001828103825260288152602001806141a16028913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60008183613fe55760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613faa578181015183820152602001613f92565b50505050905090810190601f168015613fd75780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581613ff157fe5b0495945050505050565b6000818484111561404d5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315613faa578181015183820152602001613f92565b50505090039056fe4d6f727068657253746174653a2043616c6c6572206973206e6f7420746865204272696467652e2041626f7274696e672e4d6f727068657253746174653a2052657761726420626173697320706f696e7473206e65656420746f206265206c657373206f7220657175616c20746f2031353030302e4d6f727068657253746174653a204f6e6c7920506c6174666f726d20697320616c6c6f77656420746f2065786563757465206f7065726174696f6e2e4d6f727068657253746174653a204c6576657261676520707265636973696f6e206973203165384d6f727068657253746174653a2043616c6c696e6720636f6e7472616374206e6f742074686520476f7665726e616e636520436f6e74726163742e2041626f7274696e672e4d6f727068657253746174653a2043616e206f6e6c792062652063616c6c6564206f6e206d61696e636861696e2e4f776e61626c653a207573652072656e6f756e6365206f776e65727368697020696e73746561642e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774d6f727068657253746174653a2043616c6c6572206973206e6f74207468652053696465636861696e204f70657261746f722e2041626f7274696e672e4d6f727068657253746174653a2052657761726420626173697320706f696e74732063616e206f6e6c7920626520736574206f6e20457468657265756d2e4d6f727068657253746174653a2043616c6c6572206973206e6f74207468652041646d696e6973747261746f722e2041626f7274696e672e4d6f727068657253746174653a20436f6e7472616374207061757365642c2061626f7274696e674f776e61626c653a2063616c6c65722073686f756c64206265206f776e65722ea265627a7a72315820160459360f99868cb32b4e506044eeea98d9c28ae8691a9461867be3f47ceaa764736f6c63430005100032

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

000000000000000000000000000000000000000000000000000000000000000100000000000000000000000070dcdb66e128738189012dee12d7e13b377a1d3b000000000000000000000000e261d68bda5bd518598e31320ede6e1e2d53682f

-----Decoded View---------------
Arg [0] : _mainChain (bool): True
Arg [1] : _sideChainOperator (address): 0x70Dcdb66E128738189012dee12d7e13b377A1D3B
Arg [2] : _morpherTreasury (address): 0xE261D68bDa5BD518598E31320edE6E1E2d53682f

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [1] : 00000000000000000000000070dcdb66e128738189012dee12d7e13b377a1d3b
Arg [2] : 000000000000000000000000e261d68bda5bd518598e31320ede6e1e2d53682f


Deployed Bytecode Sourcemap

513:33429:10:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;513:33429:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23210:503;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;23210:503:10;;:::i;:::-;;24288:185;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;24288:185:10;;:::i;15142:125::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15142:125:10;-1:-1:-1;;;;;15142:125:10;;:::i;14275:175::-;;;:::i;:::-;;;;;;;;;;;;;;;;1156:32;;;:::i;:::-;;;;-1:-1:-1;;;;;1156:32:10;;;;;;;;;;;;;;16815:158;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;16815:158:10;-1:-1:-1;;;;;16815:158:10;;:::i;20958:153::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;20958:153:10;;;;;;;;;;:::i;675:31::-;;;:::i;17843:128::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;17843:128:10;-1:-1:-1;;;;;17843:128:10;;:::i;:::-;;;;;;;;;;;;;;;;;;26065:112;;;:::i;28242:666::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;28242:666:10;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21336:215;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;21336:215:10;-1:-1:-1;;;;;21336:215:10;;:::i;17142:124::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;17142:124:10;-1:-1:-1;;;;;17142:124:10;;:::i;25904:155::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;25904:155:10;-1:-1:-1;;;;;25904:155:10;;:::i;22683:94::-;;;:::i;11643:176::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;11643:176:10;;;-1:-1:-1;;;;;11643:176:10;;;;;;;;;;:::i;612:26::-;;;:::i;30154:171::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;30154:171:10;;;;;;;;:::i;712:32::-;;;:::i;3682:35::-;;;:::i;11043:172::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;11043:172:10;;;;;;;:::i;12254:148::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;12254:148:10;-1:-1:-1;;;;;12254:148:10;;:::i;25771:127::-;;;:::i;21557:116::-;;;:::i;22400:93::-;;;:::i;10851:186::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;10851:186:10;;;;;;;:::i;12045:203::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;12045:203:10;;;;;;;;:::i;12760:146::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;12760:146:10;-1:-1:-1;;;;;12760:146:10;;:::i;29803:171::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;29803:171:10;;;;;;;;:::i;750:38::-;;;:::i;18760:450::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;18760:450:10;;;;;;;;:::i;12408:346::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;12408:346:10;;;;;;;;:::i;14746:170::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;14746:170:10;;:::i;21946:176::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;21946:176:10;-1:-1:-1;;;;;21946:176:10;;:::i;24479:125::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;24479:125:10;;:::i;25488:277::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;25488:277:10;;:::i;1516:52::-;;;:::i;14456:133::-;;;:::i;25146:125::-;;;:::i;15708:144::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15708:144:10;-1:-1:-1;;;;;15708:144:10;;:::i;981:26::-;;;:::i;23014:190::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;23014:190:10;-1:-1:-1;;;;;23014:190:10;;:::i;16979:157::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;16979:157:10;-1:-1:-1;;;;;16979:157:10;;:::i;644:25::-;;;:::i;30901:186::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;30901:186:10;;;;;;;;:::i;10665:180::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;10665:180:10;;;;;;-1:-1:-1;;;;;10665:180:10;;:::i;16219:226::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;16219:226:10;;:::i;15423:157::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;15423:157:10;;;;;;;;:::i;33564:376::-;;;:::i;1228:27::-;;;:::i;20627:123::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;20627:123:10;-1:-1:-1;;;;;20627:123:10;;:::i;1482:137:13:-;;;:::i;21830:110:10:-;;;:::i;16079:134::-;;;:::i;28914:710::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;28914:710:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;1376:47::-;;;:::i;24902:111::-;;;:::i;29630:167::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;29630:167:10;;;;;;;;:::i;4160:36::-;;;:::i;682:77:13:-;;;:::i;17684:153:10:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;17684:153:10;-1:-1:-1;;;;;17684:153:10;;:::i;1038:90:13:-;;;:::i;11221:235:10:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;11221:235:10;;;-1:-1:-1;;;;;11221:235:10;;;;;;;;;;:::i;1300:29::-;;;:::i;19216:532::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;19216:532:10;;;;;;;;:::i;15858:215::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15858:215:10;;:::i;13935:156::-;;;:::i;13335:433::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13335:433:10;;:::i;1014:32::-;;;:::i;11462:175::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;11462:175:10;;;-1:-1:-1;;;;;11462:175:10;;;;;;;;;;:::i;3584:45::-;;;:::i;3635:41::-;;;:::i;24108:174::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;24108:174:10;;:::i;17528:150::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;17528:150:10;-1:-1:-1;;;;;17528:150:10;;:::i;14097:172::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;14097:172:10;;:::i;262:21:13:-;;;:::i;14595:145:10:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;14595:145:10;;:::i;3769:28::-;;;:::i;1262:32::-;;;:::i;22230:164::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;22230:164:10;-1:-1:-1;;;;;22230:164:10;;:::i;15586:116::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15586:116:10;-1:-1:-1;;;;;15586:116:10;;:::i;26556:1680::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;26556:1680:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;18187:567::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;18187:567:10;;;;;;;;;;;;;;;;;:::i;1121:29::-;;;:::i;585:21::-;;;:::i;15273:144::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15273:144:10;-1:-1:-1;;;;;15273:144:10;;:::i;20386:235::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;20386:235:10;;:::i;21679:145::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;21679:145:10;-1:-1:-1;;;;;21679:145:10;;:::i;3723:40::-;;;:::i;13076:253::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13076:253:10;;:::i;25019:121::-;;;:::i;3803:32::-;;;:::i;20756:196::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;20756:196:10;;;;;;;;;;;;;;;;;:::i;24610:286::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;24610:286:10;;:::i;2498:184:13:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;2498:184:13;;;;;;;;:::i;22499:178:10:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;22499:178:10;-1:-1:-1;;;;;22499:178:10;;:::i;30331:180::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;30331:180:10;;;;;;;;:::i;22128:96::-;;;:::i;1194:28::-;;;:::i;26183:153::-;;;:::i;20164:216::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;20164:216:10;;:::i;12912:158::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;12912:158:10;-1:-1:-1;;;;;12912:158:10;;:::i;29980:168::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;29980:168:10;;;;;;;;:::i;10499:160::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;10499:160:10;;:::i;30517:183::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;30517:183:10;;;;;;;;:::i;1790:107:13:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1790:107:13;-1:-1:-1;;;;;1790:107:13;;:::i;1087:28:10:-;;;:::i;1052:29::-;;;:::i;30706:189::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;30706:189:10;;;;;;;;:::i;1336:34::-;;;:::i;13774:155::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13774:155:10;;:::i;16451:141::-;;;:::i;23210:503::-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;23302:9:10;;-1:-1:-1;;;23302:9:10;;;;:17;;23315:4;23302:17;23298:291;;;23368:5;23343:21;:30;;23335:111;;;;-1:-1:-1;;;23335:111:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23298:291;;;23485:26;;23477:101;;;;-1:-1:-1;;;23477:101:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23598:17;:41;;;23668:14;;23654:52;;23618:21;;-1:-1:-1;;;;;23668:14:10;;23654:52;;23668:14;;23654:52;23210:503;:::o;24288:185::-;7886:18;:16;:18::i;:::-;-1:-1:-1;;;;;7872:32:10;:10;-1:-1:-1;;;;;7872:32:10;;7864:101;;;;-1:-1:-1;;;7864:101:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24410:5;24376:31;;;:12;:31;;;;;;:39;;-1:-1:-1;;24376:39:10;;;24430:36;24389:17;;24430:36;;;24288:185;:::o;15142:125::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;15219:26:10;;;;;:16;:26;;;;;15248:12;15219:41;;15142:125::o;14275:175::-;14328:14;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14354:13;:15;;;;;;;;14384:29;;;;;;;;;;;;;;;;-1:-1:-1;14430:13:10;;14275:175;:::o;1156:32::-;;;-1:-1:-1;;;;;1156:32:10;;:::o;16815:158::-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;-1:-1:-1;;;;;16881:21:10;;;;;;:11;:21;;;;;;:28;;-1:-1:-1;;16881:28:10;16905:4;16881:28;;;16924:42;16953:12;;16881:21;16924:42;;;16815:158;:::o;20958:153::-;-1:-1:-1;;;;;21075:20:10;;;21039:17;21075:20;;;:7;:20;;;;;;;;:29;;;;;;;;;;20958:153;;;;;:::o;675:31::-;;;;:::o;17843:128::-;-1:-1:-1;;;;;17939:25:10;17905:15;17939:25;;;:15;:25;;;;;;;;;17843:128::o;26065:112::-;26153:17;;-1:-1:-1;;;;;26153:17:10;26065:112;:::o;28242:666::-;-1:-1:-1;;;;;28572:19:10;;;;28352;28572;;;:9;:19;;;;;;;;:30;;;;;;;:41;;;;28623:42;;;;28675:45;;;;28730:46;;;;28786:48;;;;28844:47;;;;;28572:41;;28623:42;;28675:45;;28730:46;;28242:666::o;21336:215::-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;21433:17:10;:49;;-1:-1:-1;;;;;;21433:49:10;;-1:-1:-1;;;;;21433:49:10;;;;;;;;;;;;21497:47;;;;-1:-1:-1;;21497:47:10;21336:215;:::o;17142:124::-;-1:-1:-1;;;;;17238:21:10;17204:15;17238:21;;;:11;:21;;;;;;;;;17142:124::o;25904:155::-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;25979:17:10;:28;;-1:-1:-1;;;;;;25979:28:10;-1:-1:-1;;;;;25979:28:10;;;;;;;;26022:30;;;;-1:-1:-1;;26022:30:10;25904:155;:::o;22683:94::-;22757:13;;-1:-1:-1;;;;;22757:13:10;22683:94;:::o;11643:176::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11761:27;;;;:16;:27;;;;;;;;:40;;;:32;;;;:40;;;;;:51;;-1:-1:-1;;;;;;11761:51:10;-1:-1:-1;;;;;11761:51:10;;;;;;;;;11643:176::o;612:26::-;;;;:::o;30154:171::-;-1:-1:-1;;;;;30275:19:10;;;;30236:20;30275:19;;;:9;:19;;;;;;;;:30;;;;;;;:42;;;;30154:171::o;712:32::-;;;;:::o;3682:35::-;;;;:::o;11043:172::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11146:27;;;;:16;:27;;;;;;:62;11043:172::o;12254:148::-;-1:-1:-1;;;;;12362:33:10;12329:14;12362:33;;;:23;:33;;;;;;;12254:148::o;25771:127::-;25872:19;;25771:127;:::o;21557:116::-;21649:17;;;;;-1:-1:-1;;;;;21649:17:10;;21557:116::o;22400:93::-;22474:12;;-1:-1:-1;;;;;22474:12:10;22400:93;:::o;10851:186::-;10948:16;10983:27;;;:16;:27;;;;;;;;:47;;;:32;;;;:47;;;;;-1:-1:-1;;;;;10983:47:10;;10851:186::o;12045:203::-;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;12143:33:10;;;;;;:23;:33;;;;;;;;;:42;;;12200:41;;;;;;;;;;;;;;;;;;;;;;12045:203;;:::o;12760:146::-;-1:-1:-1;;;;;12867:32:10;12834:14;12867:32;;;:22;:32;;;;;;;12760:146::o;29803:171::-;-1:-1:-1;;;;;29924:19:10;;;;29885:20;29924:19;;;:9;:19;;;;;;;;:30;;;;;;;:42;;29803:171::o;750:38::-;;;;:::o;18760:450::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7415:6;;;;:15;7407:67;;;;-1:-1:-1;;;7407:67:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;18869:18:10;;;;;;:8;:18;;;;;;:30;;18892:6;18869:30;:22;:30;:::i;:::-;-1:-1:-1;;;;;18848:18:10;;;;;;:8;:18;;;;;:51;18922:10;;:22;;18937:6;18922:22;:14;:22;:::i;:::-;18909:10;:35;18954:19;:17;:19::i;:::-;18997:12;;18983:70;;;-1:-1:-1;;;18983:70:10;;18997:12;18983:70;;;;;;-1:-1:-1;;;;;18983:70:10;;;;;;;;;;;;;;;18997:12;;;;;18983:40;;:70;;;;;;;;;;18997:12;;18983:70;;;5:2:-1;;;;30:1;27;20:12;5:2;18983:70:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;19091:10:10;;19068:34;;;;;;;;;;;;;;;-1:-1:-1;;;;;19068:34:10;;;-1:-1:-1;19068:34:10;;-1:-1:-1;19068:34:10;;;;;;;-1:-1:-1;;;;;19183:18:10;;;;;;:8;:18;;;;;;19158:44;;19173:8;;19158:14;:44::i;:::-;-1:-1:-1;;;;;19117:86:10;;19138:18;;;;:8;:18;;;;;;;;;;19117:86;;;;;;;;;;;;;;;;;18760:450;;:::o;12408:346::-;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;12505:32:10;;;;;;:22;:32;;;;;;;;:41;;;12556:26;:36;;;;12595:3;12556:42;;12713:32;;12688:58;;12528:8;;12688:14;:58::i;:::-;-1:-1:-1;;;;;12654:32:10;;;;;;:22;:32;;;;;;;;;;12613:134;;;;;;;;;;;;;;;;;;;;;;;;;12408:346;;:::o;14746:170::-;14829:20;14868:41;;;:26;:41;;;;;;;;;14746:170::o;21946:176::-;7714:15;:13;:15::i;:::-;-1:-1:-1;;;;;7700:29:10;:10;-1:-1:-1;;;;;7700:29:10;;7692:111;;;;-1:-1:-1;;;7692:111:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22033:14;:35;;-1:-1:-1;;;;;;22033:35:10;-1:-1:-1;;;;;22033:35:10;;;;;;;;22083:32;;;;-1:-1:-1;;22083:32:10;21946:176;:::o;24479:125::-;24543:12;24574:23;;;:12;:23;;;;;;;;;24479:125::o;25488:277::-;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25578:19;:42;;;25665:3;25630:32;:38;25711:47;;25600:20;;25711:47;;-1:-1:-1;;25711:47:10;25488:277;:::o;1516:52::-;;;;:::o;14456:133::-;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14516:20;:28;;-1:-1:-1;;14516:28:10;;;14559:23;;;;14539:5;;14559:23;14456:133::o;25146:125::-;7886:18;:16;:18::i;:::-;-1:-1:-1;;;;;7872:32:10;:10;-1:-1:-1;;;;;7872:32:10;;7864:101;;;;-1:-1:-1;;;7864:101:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25205:6;:14;;-1:-1:-1;;25205:14:10;;;25234:30;;;25246:10;25234:30;;25214:5;25234:30;;;;;;;;;;;;;;;;;25146:125::o;15708:144::-;-1:-1:-1;;;;;15819:26:10;15775:25;15819:26;;;:16;:26;;;;;;;15708:144::o;981:26::-;;;;;;:::o;23014:190::-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;23095:14:10;:35;;-1:-1:-1;;;;;;23095:35:10;-1:-1:-1;;;;;23095:35:10;;;;;;;;23179:17;;23145:52;;23179:17;;23095:35;23145:52;;-1:-1:-1;;23145:52:10;23014:190;:::o;16979:157::-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;-1:-1:-1;;;;;17044:21:10;;17068:5;17044:21;;;:11;:21;;;;;;:29;;-1:-1:-1;;17044:29:10;;;17088:41;17116:12;;17044:21;17088:41;;;16979:157;:::o;644:25::-;;;;:::o;30901:186::-;-1:-1:-1;;;;;31032:19:10;;;;30988:25;31032:19;;;:9;:19;;;;;;;;:30;;;;;;;:47;;;;30901:186::o;10665:180::-;10755:21;10795:27;;;:16;:27;;;;;;;;-1:-1:-1;;;;;10795:43:10;;;;:33;;:43;;;;;;10665:180;;;;:::o;16219:226::-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;16316:24:10;:52;;;16383:55;;16343:25;;16383:55;;;;;16219:226;:::o;15423:157::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;15527:26:10;;;;;;;:16;:26;;;;;:46;15423:157::o;33564:376::-;8496:9;;-1:-1:-1;;;8496:9:10;;;;:17;;8509:4;8496:17;8488:76;;;;-1:-1:-1;;;8488:76:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33635:14;;:32;;969:6;33635:32;:18;:32;:::i;:::-;33629:3;:38;33625:309;;;33683:15;33701:49;890:5;33701:34;33717:17;;33701:11;;:15;;:34;;;;:::i;:::-;:38;:49;:38;:49;:::i;:::-;33683:67;;33764:51;33782:32;969:6;33782:14;;:18;;:32;;;;:::i;:::-;33764:17;:51::i;:::-;33834:14;;33829:29;;-1:-1:-1;;;;;33834:14:10;33850:7;33829:4;:29::i;:::-;33899:14;;33877:46;;;;;;;;-1:-1:-1;;;;;33899:14:10;;;;33877:46;;;;;;;;;33625:309;;33564:376::o;1228:27::-;;;-1:-1:-1;;;;;1228:27:10;;:::o;20627:123::-;-1:-1:-1;;;;;20722:21:10;20688:15;20722:21;;;:8;:21;;;;;;;20627:123::o;1482:137:13:-;886:9;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;1580:1;1564:6;;1543:40;;-1:-1:-1;;;;;1564:6:13;;;;1543:40;;1580:1;;1543:40;1610:1;1593:19;;-1:-1:-1;;;;;;1593:19:13;;;1482:137::o;21830:110:10:-;21920:13;;-1:-1:-1;;;;;21920:13:10;21830:110;:::o;16079:134::-;16185:21;;16079:134;:::o;28914:710::-;29299:308;;;;;;;;-1:-1:-1;;29299:308:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;29299:308:10;;;;;;29276:341;;;;;;28914:710::o;1376:47::-;;;;:::o;24902:111::-;24991:15;;24902:111;:::o;29630:167::-;29753:36;;;;;;;;-1:-1:-1;;29753:36:10;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;29753:36:10;;;;;;29743:47;;;;;;29630:167::o;4160:36::-;;;;:::o;682:77:13:-;720:7;746:6;-1:-1:-1;;;;;746:6:13;682:77;:::o;17684:153:10:-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;-1:-1:-1;;;;;17755:25:10;;17783:5;17755:25;;;:15;:25;;;;;;:33;;-1:-1:-1;;17755:33:10;;;17803:27;;;17783:5;17803:27;17684:153;:::o;1038:90:13:-;1078:4;1115:6;-1:-1:-1;;;;;1115:6:13;1101:10;:20;;1038:90::o;11221:235:10:-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11333:52;11357:9;11368:8;11378:6;11333:23;:52::i;:::-;11395:54;11421:9;11432:8;11442:6;11395:25;:54::i;:::-;11221:235;;;:::o;1300:29::-;;;;:::o;19216:532::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7415:6;;;;:15;7407:67;;;;-1:-1:-1;;;7407:67:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;19312:18:10;;;;;;:8;:18;;;;;;:28;-1:-1:-1;19312:28:10;19304:72;;;;;-1:-1:-1;;;19304:72:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;19407:18:10;;;;;;:8;:18;;;;;;:30;;19430:6;19407:30;:22;:30;:::i;:::-;-1:-1:-1;;;;;19386:18:10;;;;;;:8;:18;;;;;:51;19460:10;;:22;;19475:6;19460:22;:14;:22;:::i;:::-;19447:10;:35;19492:19;:17;:19::i;:::-;19535:12;;19521:70;;;-1:-1:-1;;;19521:70:10;;-1:-1:-1;;;;;19521:70:10;;;;;;;19535:12;19521:70;;;;;;;;;;;;;;19535:12;;;19521:40;;:70;;;;;19535:12;;19521:70;;;;;;19535:12;;19521:70;;;5:2:-1;;;;30:1;27;20:12;5:2;19521:70:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;19629:10:10;;19606:34;;;;;;;;;;;;;;;-1:-1:-1;;;;;19606:34:10;;;-1:-1:-1;19606:34:10;;-1:-1:-1;19606:34:10;;;;;;;-1:-1:-1;;;;;19721:18:10;;;;;;:8;:18;;;;;;19696:44;;19711:8;;19696:14;:44::i;15858:215::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15954:21;:46;;;16015:51;;;;;;;;;;;;;;;;;15858:215;:::o;13935:156::-;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14035:1;14006:26;:30;;;14051:33;;;;14035:1;14051:33;13935:156::o;13335:433::-;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13449:7;13420:26;;:36;13416:196;;;13501:26;;:39;;13532:7;13501:39;:30;:39;:::i;:::-;13472:26;:68;13416:196;;;13600:1;13571:26;:30;13416:196;13654:3;13621:30;:36;;;13702:26;;13672:89;;;;;;;;;;;;;;;;;;;;;;;;;;13335:433;:::o;1014:32::-;;;;;;-1:-1:-1;;;;;1014:32:10;;:::o;11462:175::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11578:27;;;;:16;:27;;;;;;;;-1:-1:-1;;;;;11578:43:10;;;;;:33;;;;:43;;;;:52;11462:175::o;3584:45::-;;;;:::o;3635:41::-;;;;:::o;24108:174::-;7886:18;:16;:18::i;:::-;-1:-1:-1;;;;;7872:32:10;:10;-1:-1:-1;;;;;7872:32:10;;7864:101;;;;-1:-1:-1;;;7864:101:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24192:29;;;;:12;:29;;;;;;:36;;-1:-1:-1;;24192:36:10;24224:4;24192:36;;;24243:32;24205:15;;24243:32;;;24108:174;:::o;17528:150::-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;-1:-1:-1;;;;;17598:25:10;;;;;;:15;:25;;;;;;:32;;-1:-1:-1;;17598:32:10;17626:4;17598:32;;;17645:26;;;17598:25;17645:26;17528:150;:::o;14097:172::-;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14177:16;:32;;;14224:38;;;;;;;;;;;;;;;;;;;14097:172;:::o;262:21:13:-;;;-1:-1:-1;;;;;262:21:13;;:::o;14595:145:10:-;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14685:41;;;;:26;:41;;;;;:48;;-1:-1:-1;;14685:48:10;14729:4;14685:48;;;14595:145::o;3769:28::-;;;;:::o;1262:32::-;;;;:::o;22230:164::-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;22310:12:10;:32;;-1:-1:-1;;;;;;22310:32:10;-1:-1:-1;;;;;22310:32:10;;;;;;;;22357:30;;;;-1:-1:-1;;22357:30:10;22230:164;:::o;15586:116::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;15667:26:10;;;;;:16;:26;;;;;:28;;;;;;15586:116::o;26556:1680::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;26891:19:10;;;;;;:9;:19;;;;;;;;:30;;;;;;;;:55;;;26956:41;;;:55;;;27021:42;;;:57;;;27088:45;;;:63;;;27161:46;;;:65;;;27236:48;;;:69;;;27315:47;;:67;;;27438:267;26891:19;:30;:55;26956;27021:57;27088:63;27161:65;27236:69;27315:67;27438:15;:267::i;:::-;-1:-1:-1;;;;;27392:19:10;;;;;;:9;:19;;;;;;;;:30;;;;;;;;:43;;:313;27719:15;;;;:35;;;27753:1;27738:12;:16;27719:35;27715:180;;;27770:40;27790:9;27801:8;27770:19;:40::i;:::-;27715:180;;;27841:43;27864:9;27875:8;27841:22;:43::i;:::-;-1:-1:-1;;;;;27909:320:10;;27934:19;;;;:9;:19;;;;;;;;:30;;;;;;;;;:43;;;27909:320;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28013:9;;27909:320;27934:43;27909:320;;;;;;;;;;26556:1680;;;;;;;;;:::o;18187:567::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7415:6;;;;:15;7407:67;;;;-1:-1:-1;;;7407:67:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;18297:15:10;;;;;;:8;:15;;;;;;:25;-1:-1:-1;18297:25:10;18289:69;;;;;-1:-1:-1;;;18289:69:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;18386:15:10;;;;;;:8;:15;;;;;;:27;;18406:6;18386:27;:19;:27;:::i;:::-;-1:-1:-1;;;;;18368:15:10;;;;;;;:8;:15;;;;;;:45;;;;18439:13;;;;;;;:25;;18457:6;18439:25;:17;:25;:::i;:::-;-1:-1:-1;;;;;18423:13:10;;;;;;;:8;:13;;;;;;:41;;;;18488:12;;18474:60;;-1:-1:-1;;;18474:60:10;;;;;;;;;;;;;;;;;;;;;;;;18488:12;;;;;18474:40;;:60;;;;;18423:13;;18474:60;;;;;;18423:13;18488:12;18474:60;;;5:2:-1;;;;30:1;27;20:12;5:2;18474:60:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;18549:28:10;;;;;;;;-1:-1:-1;;;;;18549:28:10;;;;-1:-1:-1;18549:28:10;;;-1:-1:-1;18549:28:10;;;;;;;;;-1:-1:-1;;;;;18649:15:10;;;;;;:8;:15;;;;;;18627:38;;18642:5;;18627:14;:38::i;:::-;-1:-1:-1;;;;;18592:74:10;;18610:15;;;;:8;:15;;;;;;;;;;18592:74;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;18732:13:10;;;;;;:8;:13;;;;;;18712:34;;18727:3;;18712:14;:34::i;:::-;-1:-1:-1;;;;;18681:66:10;;18697:13;;;;:8;:13;;;;;;;;;;18681:66;;;;;;;;;;;;;;;;;18187:567;;;:::o;1121:29::-;;;-1:-1:-1;;;;;1121:29:10;;:::o;585:21::-;;;-1:-1:-1;;;585:21:10;;;;;:::o;15273:144::-;-1:-1:-1;;;;;15384:26:10;15340:25;15384:26;;;:16;:26;;;;;;;15273:144::o;20386:235::-;8052:17;;-1:-1:-1;;;;;8052:17:10;8038:10;:31;8030:105;;;;-1:-1:-1;;;8030:105:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20486:17;:41;;;20537:19;:17;:19::i;:::-;20571:43;;;;;;;;;;;;;;;;;20386:235;:::o;21679:145::-;886:9:13;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;21752:13:10;:26;;-1:-1:-1;;;;;21752:26:10;;-1:-1:-1;;;;;;21752:26:10;;;;;;;;21793:24;;;;;;;;;;;;;;;;21679:145;:::o;3723:40::-;;;;:::o;13076:253::-;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13179:26;;:39;;13210:7;13179:39;:30;:39;:::i;:::-;13150:26;:68;;;13291:30;;13233:89;;;;;;;;;;;;;;;;;;;;;;;;;13076:253;:::o;25019:121::-;7886:18;:16;:18::i;:::-;-1:-1:-1;;;;;7872:32:10;:10;-1:-1:-1;;;;;7872:32:10;;7864:101;;;;-1:-1:-1;;;7864:101:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25076:6;:13;;-1:-1:-1;;25076:13:10;25085:4;25076:13;;;;;;25104:29;;;25116:10;25104:29;;;;;;;;;;;;;;;;;;;;;25019:121::o;3803:32::-;;;;;;:::o;20756:196::-;7550:10;7538:23;;;;:11;:23;;;;;;;;:31;;:23;:31;7530:104;;;;-1:-1:-1;;;7530:104:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;20858:14:10;;;;;;;:7;:14;;;;;;;;:24;;;;;;;;;;;;;:34;;;20907:38;;;;;;;;;;;;;;;;;20756:196;;;:::o;24610:286::-;7886:18;:16;:18::i;:::-;-1:-1:-1;;;;;7872:32:10;:10;-1:-1:-1;;;;;7872:32:10;;7864:101;;;;-1:-1:-1;;;7864:101:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;890:5;24710:19;:31;24702:83;;;;-1:-1:-1;;;24702:83:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24795:15;:37;;;24847:42;;;;;;;;;;;;;;;;;24610:286;:::o;2498:184:13:-;2595:13;886:9;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;2634:13;-1:-1:-1;;;;;2627:30:13;;2658:7;:5;:7::i;:::-;2667;2627:48;;;;;;;;;;;;;-1:-1:-1;;;;;2627:48:13;-1:-1:-1;;;;;2627:48:13;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2627:48:13;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;2627:48:13;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;2627:48:13;;2498:184;-1:-1:-1;;;2498:184:13:o;22499:178:10:-;7714:15;:13;:15::i;:::-;-1:-1:-1;;;;;7700:29:10;:10;-1:-1:-1;;;;;7700:29:10;;7692:111;;;;-1:-1:-1;;;7692:111:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22584:13;:33;;-1:-1:-1;;;;;;22584:33:10;-1:-1:-1;;;;;22584:33:10;;;;;;;;22632:38;;;;-1:-1:-1;;22632:38:10;22499:178;:::o;30331:180::-;-1:-1:-1;;;;;30458:19:10;;;;30416:23;30458:19;;;:9;:19;;;;;;;;:30;;;;;;;:45;;;;30331:180::o;22128:96::-;22203:14;;-1:-1:-1;;;;;22203:14:10;22128:96;:::o;1194:28::-;;;-1:-1:-1;;;;;1194:28:10;;:::o;26183:153::-;26297:32;;26183:153;:::o;20164:216::-;7886:18;:16;:18::i;:::-;-1:-1:-1;;;;;7872:32:10;:10;-1:-1:-1;;;;;7872:32:10;;7864:101;;;;-1:-1:-1;;;7864:101:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20255:16;:36;;;20301:19;:17;:19::i;:::-;20335:38;;;;;;;;;;;;;;;;;20164:216;:::o;12912:158::-;-1:-1:-1;;;;;13027:36:10;12990:18;13027:36;;;:26;:36;;;;;;;12912:158::o;29980:168::-;-1:-1:-1;;;;;30099:19:10;;;;30061;30099;;;:9;:19;;;;;;;;:30;;;;;;;:41;;;;29980:168::o;10499:160::-;10566:24;10609:27;;;:16;:27;;;;;:43;;10499:160::o;30517:183::-;-1:-1:-1;;;;;30646:19:10;;;;30603:24;30646:19;;;:9;:19;;;;;;;;:30;;;;;;;:46;;;;30517:183::o;1790:107:13:-;886:9;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:13;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:13;;;;;;;;;;;;;;;1862:28;1881:8;1862:18;:28::i;:::-;1790:107;:::o;1087:28:10:-;;;-1:-1:-1;;;;;1087:28:10;;:::o;1052:29::-;;;-1:-1:-1;;;;;1052:29:10;;:::o;30706:189::-;-1:-1:-1;;;;;30839:19:10;;;;30794:26;30839:19;;;:9;:19;;;;;;;;:30;;;;;;;:48;;;;30706:189::o;1336:34::-;;;;:::o;13774:155::-;8359:18;:16;:18::i;:::-;-1:-1:-1;;;;;8345:32:10;:10;-1:-1:-1;;;;;8345:32:10;;8337:94;;;;-1:-1:-1;;;8337:94:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13850:20;:29;;;13894:28;;;;;;;;;;;;;;;;;13774:155;:::o;16451:141::-;16561:24;;16451:141;:::o;834:176:14:-;892:7;923:5;;;946:6;;;;938:46;;;;;-1:-1:-1;;;938:46:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;1002:1;834:176;-1:-1:-1;;;834:176:14:o;19993:165:10:-;20054:55;20091:17;;20054:32;20069:16;;20054:10;;:14;;:32;;;;:::i;:::-;:36;:55;:36;:55;:::i;:::-;20040:11;:69;;;20124:27;;;;;;;;;;;;;;;;19993:165::o;2159:459:14:-;2217:7;2458:6;2454:45;;-1:-1:-1;2487:1:14;2480:8;;2454:45;2521:5;;;2525:1;2521;:5;:1;2544:5;;;;;:10;2536:56;;;;-1:-1:-1;;;2536:56:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3073:130;3131:7;3157:39;3161:1;3164;3157:39;;;;;;;;;;;;;;;;;:3;:39::i;23719:155:10:-;23789:14;:32;;;23836:31;;23806:15;;23836:31;;;;;23719:155;:::o;1274:134:14:-;1332:7;1358:43;1362:1;1365;1358:43;;;;;;;;;;;;;;;;;:3;:43::i;31372:455:10:-;31501:24;31528:42;31552:7;31561:8;31528:23;:42::i;:::-;31501:69;-1:-1:-1;31584:21:10;31580:241;;31621:24;31648:34;31680:1;31648:27;31667:7;31648:18;:27::i;:34::-;31621:61;;31696:45;31715:7;31724:16;31696:18;:45::i;:::-;31755:55;31774:7;31783:8;31793:16;31755:18;:55::i;:::-;31580:241;31372:455;;;:::o;31833:1321::-;31953:24;31980:42;32004:7;32013:8;31980:23;:42::i;:::-;31953:69;;32071:18;32092:27;32111:7;32092:18;:27::i;:::-;32071:48;;32129:20;32152:46;32178:7;32187:10;32152:25;:46::i;:::-;32129:69;-1:-1:-1;32330:20:10;;32326:822;;32558:10;32539:16;:29;32535:216;;;32588:66;32614:7;32623:12;32637:16;32588:25;:66::i;:::-;32672:64;32696:7;32705:12;32719:16;32672:23;:64::i;:::-;32850:58;32876:7;32893:1;32897:10;32850:25;:58::i;:::-;32922:45;32946:7;32955:8;32965:1;32922:23;:45::i;:::-;33043:14;;33039:99;;33077:46;33096:7;33105:17;:10;33120:1;33105:17;:14;:17;:::i;:::-;33077:18;:46::i;:::-;31833:1321;;;;;:::o;2041:227:13:-;-1:-1:-1;;;;;2114:22:13;;2106:75;;;;-1:-1:-1;;;2106:75:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2217:6;;;2196:38;;-1:-1:-1;;;;;2196:38:13;;;;2217:6;;;2196:38;;;2244:6;:17;;-1:-1:-1;;;;;;2244:17:13;-1:-1:-1;;;;;2244:17:13;;;;;;;;;;2041:227::o;3718:338:14:-;3804:7;3904:12;3897:5;3889:28;;;;-1:-1:-1;;;3889:28:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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;3889:28:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3927:9;3943:1;3939;:5;;;;;;;3718:338;-1:-1:-1;;;;;3718:338:14:o;1732:187::-;1818:7;1853:12;1845:6;;;;1837:29;;;;-1:-1:-1;;;1837:29:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;1837:29:14;-1:-1:-1;;;1888:5:14;;;1732:187::o

Swarm Source

bzzr://160459360f99868cb32b4e506044eeea98d9c28ae8691a9461867be3f47ceaa7

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

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