ETH Price: $3,268.24 (-0.21%)
Gas: 2 Gwei

Token

 

Overview

Max Total Supply

1,390,238,645,294,022,096,163,357,409

Holders

886

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 0 Decimals)

Balance
2,000,000,000,000,000,000,000

Value
$0.00
0xcdd7684850dbe2adf61e5e92595acd0f90d33eb2
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
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 11 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 1 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 2 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 3 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 4 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 5 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 6 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 7 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 8 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 9 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 10 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
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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