ETH Price: $2,331.90 (+10.31%)

Contract

0x62e26AB4444E24E42e63A0857bF56Ea1c70AAEc8
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

View more zero value Internal Transactions in Advanced View mode

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

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

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

Contract Source Code Verified (Exact Match)

Contract Name:
MorpherTradeEngine

Compiler Version
v0.5.16+commit.9c3226ce

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, GNU GPLv3 license

Contract Source Code (Solidity Multiple files format)

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

import "./Ownable.sol";
import "./SafeMath.sol";
import "./MorpherState.sol";
import "./IMorpherStaking.sol";
import "./MorpherMintingLimiter.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;
    IMorpherStaking staking;
    MorpherMintingLimiter mintingLimiter;
    using SafeMath for uint256;

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

    address public escrowOpenOrderAddress = 0x1111111111111111111111111111111111111111;
    bool public escrowOpenOrderEnabled;


    //we're locking positions in for this price at a market marketId;
    address public closedMarketPriceLock = 0x0000000000000000000000000000000000000001;


// ----------------------------------------------------------------------------
// 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;
        bytes32 marketId;
        uint256 closeSharesAmount;
        uint256 openMPHTokenAmount;
        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;
        uint256 orderEscrowAmount;
    }

    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,
        uint256 _closeSharesAmount,
        uint256 _openMPHTokenAmount,
        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);
    event LinkStaking(address _stakingAddress);
    event LinkMintingLimiter(address _mintingLimiterAddress);

    
    event LockedPriceForClosingPositions(bytes32 _marketId, uint256 _price);


    constructor(address _stateAddress, address _coldStorageOwnerAddress, address _stakingContractAddress, bool _escrowOpenOrderEnabled, uint256 _deployedTimestampOverride, address _mintingLimiterAddress) public {
        setMorpherState(_stateAddress);
        setMorpherStaking(_stakingContractAddress);
        setMorpherMintingLimiter(_mintingLimiterAddress);
        transferOwnership(_coldStorageOwnerAddress);
        escrowOpenOrderEnabled = _escrowOpenOrderEnabled;
        deployedTimeStamp = _deployedTimestampOverride > 0 ? _deployedTimestampOverride : block.timestamp;
    }

    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 setMorpherStaking(address _stakingAddress) public onlyOwner {
        staking = IMorpherStaking(_stakingAddress);
        emit LinkStaking(_stakingAddress);
    }

    function setMorpherMintingLimiter(address _mintingLimiterAddress) public onlyOwner {
        mintingLimiter = MorpherMintingLimiter(_mintingLimiterAddress);
        emit LinkMintingLimiter(_mintingLimiterAddress);
    }

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

    function setEscrowOpenOrderEnabled(bool _isEnabled) public onlyOwner {
        escrowOpenOrderEnabled = _isEnabled;
    }
    
    function paybackEscrow(bytes32 _orderId) private {
        //pay back the escrow to the user so he has it back on his balance/**
        if(orders[_orderId].orderEscrowAmount > 0) {
            //checks effects interaction
            uint256 paybackAmount = orders[_orderId].orderEscrowAmount;
            orders[_orderId].orderEscrowAmount = 0;
            state.transfer(escrowOpenOrderAddress, orders[_orderId].userId, paybackAmount);
        }
    }

    function buildupEscrow(bytes32 _orderId, uint256 _amountInMPH) private {
        if(escrowOpenOrderEnabled && _amountInMPH > 0) {
            state.transfer(orders[_orderId].userId, escrowOpenOrderAddress, _amountInMPH);
            orders[_orderId].orderEscrowAmount = _amountInMPH;
        }
    }


    function validateClosedMarketOrderConditions(address _address, bytes32 _marketId, uint256 _closeSharesAmount, uint256 _openMPHTokenAmount, bool _tradeDirection ) internal view {
        //markets active? Still tradeable?
        if(_openMPHTokenAmount > 0) {
            require(state.getMarketActive(_marketId) == true, "MorpherTradeEngine: market unknown or currently not enabled for trading.");
        } else {
            //we're just closing a position, but it needs a forever price locked in if market is not active
            //the user needs to close his complete position
            if(state.getMarketActive(_marketId) == false) {
                require(getDeactivatedMarketPrice(_marketId) > 0, "MorpherTradeEngine: Can't close a position, market not active and closing price not locked");
                if(_tradeDirection) {
                    //long
                    require(_closeSharesAmount == state.getShortShares(_address, _marketId), "MorpherTradeEngine: Deactivated market order needs all shares to be closed");
                } else {
                    //short
                    require(_closeSharesAmount == state.getLongShares(_address, _marketId), "MorpherTradeEngine: Deactivated market order needs all shares to be closed");
                }
            }
        }
    }

    //wrapper for stack too deep errors
    function validateClosedMarketOrder(bytes32 _orderId) internal view {
         validateClosedMarketOrderConditions(orders[_orderId].userId, orders[_orderId].marketId, orders[_orderId].closeSharesAmount, orders[_orderId].openMPHTokenAmount, orders[_orderId].tradeDirection);
    }

// ----------------------------------------------------------------------------
// requestOrderId(address _address, bytes32 _marketId, bool _closeSharesAmount, uint256 _openMPHTokenAmount, 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,
        uint256 _closeSharesAmount,
        uint256 _openMPHTokenAmount,
        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.");

        validateClosedMarketOrderConditions(_address, _marketId, _closeSharesAmount, _openMPHTokenAmount, _tradeDirection);

        //request limits
        require(state.getNumberOfRequests(_address) <= state.getNumberOfRequestsLimit() ||
            state.getLastRequestBlock(_address) < block.number,
            "MorpherTradeEngine: request exceeded maximum permitted requests per block."
        );

        /**
         * The user can't partially close a position and open another one with MPH
         */
        if(_openMPHTokenAmount > 0) {
            if(_tradeDirection) {
                //long
                require(_closeSharesAmount == state.getShortShares(_address, _marketId), "MorpherTradeEngine: Can't partially close a position and open another one in opposite direction");
            } else {
                //short
                require(_closeSharesAmount == state.getLongShares(_address, _marketId), "MorpherTradeEngine: Can't partially close a position and open another one in opposite direction");
            }
        }

        state.setLastRequestBlock(_address);
        state.increaseNumberOfRequests(_address);
        orderNonce++;
        _orderId = keccak256(
            abi.encodePacked(
                _address,
                block.number,
                _marketId,
                _closeSharesAmount,
                _openMPHTokenAmount,
                _tradeDirection,
                _orderLeverage,
                orderNonce
                )
            );
        lastOrderId = _orderId;
        orders[_orderId].userId = _address;
        orders[_orderId].marketId = _marketId;
        orders[_orderId].closeSharesAmount = _closeSharesAmount;
        orders[_orderId].openMPHTokenAmount = _openMPHTokenAmount;
        orders[_orderId].tradeDirection = _tradeDirection;
        orders[_orderId].orderLeverage = _orderLeverage;
        emit OrderIdRequested(
            _orderId,
            _address,
            _marketId,
            _closeSharesAmount,
            _openMPHTokenAmount,
            _tradeDirection,
            _orderLeverage
        );

        /**
         * put the money in escrow here if given MPH to open an order
         * - also, can only close positions if in shares, so it will
         * definitely trigger a mint there.
         * The money must be put in escrow even though we have an existing position
         */
        buildupEscrow(_orderId, _openMPHTokenAmount);

        return _orderId;
    }

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

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

    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)
        );
    }

    function setDeactivatedMarketPrice(bytes32 _marketId, uint256 _price) public onlyOracle {
         state.setPosition(
            closedMarketPriceLock,
            _marketId,
            now.mul(1000),
            0,
            0,
            _price,
            0,
            0,
            0
        );

        emit LockedPriceForClosingPositions(_marketId, _price);

    }

    function getDeactivatedMarketPrice(bytes32 _marketId) public view returns(uint256) {
        ( , , uint positionForeverClosingPrice, , ,) = state.getPosition(closedMarketPriceLock, _marketId);
        return positionForeverClosingPrice;
    }

// ----------------------------------------------------------------------------
// 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 _timeStampInMS
        ) 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.");
        
        orders[_orderId].marketPrice = _marketPrice;
        orders[_orderId].marketSpread = _marketSpread;
        orders[_orderId].timeStamp = _timeStampInMS;
        orders[_orderId].liquidationTimestamp = _liquidationTimestamp;
        
        /**
        * If the market is deactivated, then override the price with the locked in market price
        * if the price wasn't locked in: error out.
        */
        if(state.getMarketActive(orders[_orderId].marketId) == false) {
            validateClosedMarketOrder(_orderId);
            orders[_orderId].marketPrice = getDeactivatedMarketPrice(orders[_orderId].marketId);
        }
        
        // Check if previous position on that market was liquidated
        if (_liquidationTimestamp > state.getLastUpdated(orders[_orderId].userId, orders[_orderId].marketId)) {
            liquidate(_orderId);
        }
    

        paybackEscrow(_orderId);

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

        address _address = orders[_orderId].userId;
        bytes32 _marketId = orders[_orderId].marketId;
        delete orders[_orderId];
        emit OrderProcessed(
            _orderId,
            _marketPrice,
            _marketSpread,
            _liquidationTimestamp,
            _timeStampInMS,
            _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.");

        /**
         * Pay back any escrow there
         */
        paybackEscrow(_orderId);

        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 _positionTimeStampInMs,
        uint256 _marketPrice,
        uint256 _marketSpread,
        uint256 _orderLeverage,
        bool _sell
        ) public view 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 (
            getLiquidationPrice(_averagePrice, _averageLeverage, false, _positionTimeStampInMs) <= _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));
                uint256 _marginInterest = calculateMarginInterest(_averagePrice, _averageLeverage, _positionTimeStampInMs);
                if (_marginInterest <= _shareValue) {
                    _shareValue = _shareValue.sub(_marginInterest);
                } else {
                    _shareValue = 0;
                }
            } 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 _positionTimeStampInMs,
        uint256 _marketPrice,
        uint256 _marketSpread,
        uint256 _orderLeverage,
        bool _sell
        ) public view 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 <= getLiquidationPrice(_averagePrice, _averageLeverage, true, _positionTimeStampInMs)
            ) {
	        // 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));
                
                uint256 _marginInterest = calculateMarginInterest(_averagePrice, _averageLeverage, _positionTimeStampInMs);
                if (_marginInterest <= _shareValue) {
                    _shareValue = _shareValue.sub(_marginInterest);
                } else {
                    _shareValue = 0;
                }
            } else {
                // We buy a new long position and have to pay the spread
                _shareValue = _shareValue.add(_marketSpread.mul(_orderLeverage).div(PRECISION));
            }
        }
        return _shareValue;
    }

// ----------------------------------------------------------------------------
// calculateMarginInterest(uint256 _averagePrice, uint256 _averageLeverage, uint256 _positionTimeStamp)
// Calculates the interest for leveraged positions
// ----------------------------------------------------------------------------


    function calculateMarginInterest(uint256 _averagePrice, uint256 _averageLeverage, uint256 _positionTimeStampInMs) public view returns (uint256 _marginInterest) {
        if (_positionTimeStampInMs.div(1000) < deployedTimeStamp) {
            _positionTimeStampInMs = deployedTimeStamp.mul(1000);
        }
        _marginInterest = _averagePrice.mul(_averageLeverage.sub(PRECISION));
        _marginInterest = _marginInterest.mul((now.sub(_positionTimeStampInMs.div(1000)).div(86400)).add(1));
        _marginInterest = _marginInterest.mul(staking.interestRate()).div(PRECISION).div(PRECISION);
        return _marginInterest;
    }

// ----------------------------------------------------------------------------
// 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].closeSharesAmount > 0) {
            //calcualte the balanceUp/down first
            //then reopen the position with MPH amount

             // Investment was specified in shares
            if (orders[_orderId].closeSharesAmount <= state.getShortShares(orders[_orderId].userId, orders[_orderId].marketId)) {
                // Partial closing of short position
                orders[_orderId].shortSharesOrder = orders[_orderId].closeSharesAmount;
            } else {
                // Closing of entire short position
                orders[_orderId].shortSharesOrder = state.getShortShares(orders[_orderId].userId, orders[_orderId].marketId);
            }
        }

        //calculate the long shares, but only if the old position is completely closed out (if none exist shortSharesOrder = 0)
        if(
            orders[_orderId].shortSharesOrder == state.getShortShares(orders[_orderId].userId, orders[_orderId].marketId) && 
            orders[_orderId].openMPHTokenAmount > 0
        ) {
            orders[_orderId].longSharesOrder = orders[_orderId].openMPHTokenAmount.div(
                longShareValue(
                    orders[_orderId].marketPrice,
                    orders[_orderId].orderLeverage,
                    now,
                    orders[_orderId].marketPrice,
                    orders[_orderId].marketSpread,
                    orders[_orderId].orderLeverage,
                    false
            ));
        }

        // 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].closeSharesAmount > 0) {
            //calcualte the balanceUp/down first
            //then reopen the position with MPH amount

            // Investment was specified in shares
            if (orders[_orderId].closeSharesAmount <= state.getLongShares(orders[_orderId].userId, orders[_orderId].marketId)) {
                // Partial closing of long position
                orders[_orderId].longSharesOrder = orders[_orderId].closeSharesAmount;
            } else {
                // Closing of entire long position
                orders[_orderId].longSharesOrder = state.getLongShares(orders[_orderId].userId, orders[_orderId].marketId);
            }
        }

        if(
            orders[_orderId].longSharesOrder == state.getLongShares(orders[_orderId].userId, orders[_orderId].marketId) && 
            orders[_orderId].openMPHTokenAmount > 0
        ) {
        orders[_orderId].shortSharesOrder = orders[_orderId].openMPHTokenAmount.div(
                    shortShareValue(
                        orders[_orderId].marketPrice,
                        orders[_orderId].orderLeverage,
                        now,
                        orders[_orderId].marketPrice,
                        orders[_orderId].marketSpread,
                        orders[_orderId].orderLeverage,
                        false
                ));
        }
        // 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 = calculateBalanceUp(_orderId);
        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);
            resetTimestampInOrderToLastUpdated(_orderId);
        }

        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);
    }

event ResetTimestampInOrder(bytes32 _orderId, uint oldTimestamp, uint newTimestamp);
function resetTimestampInOrderToLastUpdated(bytes32 _orderId) internal {
    address userId = orders[_orderId].userId;
    bytes32 marketId = orders[_orderId].marketId;
    uint lastUpdated = state.getLastUpdated(userId, marketId);
    emit ResetTimestampInOrder(_orderId, orders[_orderId].timeStamp, lastUpdated);
    orders[_orderId].timeStamp = lastUpdated;
}

// ----------------------------------------------------------------------------
// closeShort(bytes32 _orderId)
// Closes an existing short position. Average entry price/spread/leverage do not change.
// ----------------------------------------------------------------------------
function calculateBalanceUp(bytes32 _orderId) private view returns (uint256 _balanceUp) {
        address _userId = orders[_orderId].userId;
        bytes32 _marketId = orders[_orderId].marketId;
        uint256 _shareValue;

        if (orders[_orderId].tradeDirection == false) { //we are selling our long shares
            _balanceUp = orders[_orderId].longSharesOrder;
            _shareValue = longShareValue(
                state.getMeanEntryPrice(_userId, _marketId),
                state.getMeanEntryLeverage(_userId, _marketId),
                state.getLastUpdated(_userId, _marketId),
                orders[_orderId].marketPrice,
                orders[_orderId].marketSpread,
                state.getMeanEntryLeverage(_userId, _marketId),
                true
            );
        } else { //we are going long, we are selling our short shares
            _balanceUp = orders[_orderId].shortSharesOrder;
            _shareValue = shortShareValue(
                state.getMeanEntryPrice(_userId, _marketId),
                state.getMeanEntryLeverage(_userId, _marketId),
                state.getLastUpdated(_userId, _marketId),
                orders[_orderId].marketPrice,
                orders[_orderId].marketSpread,
                state.getMeanEntryLeverage(_userId, _marketId),
                true
            );
        }
        return _balanceUp.mul(_shareValue); 
    }

    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 = calculateBalanceUp(_orderId);
        
        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);

            /**
             * we need the timestamp of the old order for partial closes, not the new one
             */
            resetTimestampInOrderToLastUpdated(_orderId);
        }

        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, orders[_orderId].timeStamp);
        }
        if (orders[_orderId].newShortShares > 0) {
            orders[_orderId].newLiquidationPrice = getLiquidationPrice(orders[_orderId].newMeanEntryPrice, orders[_orderId].newMeanEntryLeverage, false, orders[_orderId].timeStamp);
        }
        return orders[_orderId].newLiquidationPrice;
    }

    function getLiquidationPrice(uint256 _newMeanEntryPrice, uint256 _newMeanEntryLeverage, bool _long, uint _positionTimestampInMs) public view returns (uint256 _liquidationPrice) {
        if (_long == true) {
            _liquidationPrice = _newMeanEntryPrice.mul(_newMeanEntryLeverage.sub(PRECISION)).div(_newMeanEntryLeverage);
            _liquidationPrice = _liquidationPrice.add(calculateMarginInterest(_newMeanEntryPrice, _newMeanEntryLeverage, _positionTimestampInMs));
        } else {
            _liquidationPrice = _newMeanEntryPrice.mul(_newMeanEntryLeverage.add(PRECISION)).div(_newMeanEntryLeverage);
            _liquidationPrice = _liquidationPrice.sub(calculateMarginInterest(_newMeanEntryPrice, _newMeanEntryLeverage, _positionTimestampInMs));
        }
        return _liquidationPrice;
    }

    
// ----------------------------------------------------------------------------
// 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) {
            mintingLimiter.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 2 of 13: IERC20.sol
pragma solidity 0.5.16;

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

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

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

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

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

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

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

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

File 3 of 13: IMorpherStaking.sol
pragma solidity 0.5.16;
contract IMorpherStaking {
    
    function lastReward() public view returns (uint256);

    function totalShares() public view returns (uint256);

    function interestRate() public view returns (uint256);

    function lockupPeriod() public view returns (uint256);
    
    function minimumStake() public view returns (uint256);

    function stakingAdmin() public view returns (address);

    function updatePoolShareValue() public returns (uint256 _newPoolShareValue) ;

    function stake(uint256 _amount) public returns (uint256 _poolShares);

    function unStake(uint256 _numOfShares) public returns (uint256 _amount);

}

File 4 of 13: IMorpherState.sol
pragma solidity 0.5.16;

contract IMorpherState {
    function setPosition(
        address _address,
        bytes32 _marketId,
        uint256 _timeStamp,
        uint256 _longShares,
        uint256 _shortShares,
        uint256 _meanEntryPrice,
        uint256 _meanEntrySpread,
        uint256 _meanEntryLeverage,
        uint256 _liquidationPrice
    ) public; 

    function getPosition(
        address _address,
        bytes32 _marketId
    ) public view returns (
        uint256 _longShares,
        uint256 _shortShares,
        uint256 _meanEntryPrice,
        uint256 _meanEntrySpread,
        uint256 _meanEntryLeverage,
        uint256 _liquidationPrice
    );

    function getLastUpdated(address _address, bytes32 _marketId) public view returns (uint256 _lastUpdated);

    function transfer(address _from, address _to, uint256 _token) public;
    
    function balanceOf(address _tokenOwner) public view returns (uint256 balance);

    function mint(address _address, uint256 _token) public;

    function burn(address _address, uint256 _token) public;

     function getSideChainOperator() public view returns (address _address);

    function inactivityPeriod() public view returns (uint256);

    function getSideChainMerkleRootWrittenAtTime() public view returns(uint256 _sideChainMerkleRoot);

    function fastTransfersEnabled() public view returns(bool);

    function mainChain() public view returns(bool);

    function setInactivityPeriod(uint256 _periodLength) public;

    function disableFastWithdraws() public;

    function setSideChainMerkleRoot(bytes32 _sideChainMerkleRoot) public;

    function resetLast24HoursAmountWithdrawn() public;

    function set24HourWithdrawLimit(uint256 _limit) public;

    function getTokenSentToLinkedChain(address _address) public view returns (uint256 _token);

    function getTokenClaimedOnThisChain(address _address) public view returns (uint256 _token);

    function getTokenSentToLinkedChainTime(address _address) public view returns (uint256 _timeStamp);

    function lastWithdrawLimitReductionTime() public view returns (uint256);

    function withdrawLimit24Hours() public view returns (uint256);

    function update24HoursWithdrawLimit(uint256 _amount) public;

    function last24HoursAmountWithdrawn() public view returns (uint256);

    function setTokenSentToLinkedChain(address _address, uint256 _token) public;

    function setTokenClaimedOnThisChain(address _address, uint256 _token) public;

    function add24HoursWithdrawn(uint256 _amount) public;

    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);

    function getPositionClaimedOnMainChain(bytes32 _positionHash) public view returns (bool _alreadyClaimed);

    function setPositionClaimedOnMainChain(bytes32 _positionHash) public;

     function getBalanceHash(address _address, uint256 _balance) public pure returns (bytes32 _hash);

     function getSideChainMerkleRoot() public view returns(bytes32 _sideChainMerkleRoot);

     function getBridgeNonce() public returns (uint256 _nonce);
}

File 5 of 13: 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 6 of 13: 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 7 of 13: MorpherMintingLimiter.sol
pragma solidity 0.5.16;

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

contract MorpherMintingLimiter {
    using SafeMath for uint256; 

    uint256 public mintingLimit;
    uint256 public timeLockingPeriod;

    mapping(address => uint256) public escrowedTokens;
    mapping(address => uint256) public lockedUntil;

    address tradeEngineAddress; 
    MorpherState state;

    event MintingEscrowed(address _user, uint256 _tokenAmount);
    event EscrowReleased(address _user, uint256 _tokenAmount);
    event MintingDenied(address _user, uint256 _tokenAmount);
    event MintingLimitUpdated(uint256 _mintingLimitOld, uint256 _mintingLimitNew);
    event TimeLockPeriodUpdated(uint256 _timeLockPeriodOld, uint256 _timeLockPeriodNew);
    event TradeEngineAddressSet(address _tradeEngineAddress);

    modifier onlyTradeEngine() {
        require(msg.sender == tradeEngineAddress, "MorpherMintingLimiter: Only Trade Engine is allowed to call this function");
        _;
    }

    modifier onlyAdministrator() {
        require(msg.sender == state.getAdministrator(), "MorpherMintingLimiter: Only Administrator can call this function");
        _;
    }

    constructor(address _stateAddress, uint256 _mintingLimit, uint256 _timeLockingPeriodInSeconds) public {
        state = MorpherState(_stateAddress);
        mintingLimit = _mintingLimit;
        timeLockingPeriod = _timeLockingPeriodInSeconds;
    }

    function setTradeEngineAddress(address _tradeEngineAddress) public onlyAdministrator {
        emit TradeEngineAddressSet(_tradeEngineAddress);
        tradeEngineAddress = _tradeEngineAddress;
    }
    

    function setMintingLimit(uint256 _newMintingLimit) public onlyAdministrator {
        emit MintingLimitUpdated(mintingLimit, _newMintingLimit);
        mintingLimit = _newMintingLimit;
    }

    function setTimeLockingPeriod(uint256 _newTimeLockingPeriodInSeconds) public onlyAdministrator {
        emit TimeLockPeriodUpdated(timeLockingPeriod, _newTimeLockingPeriodInSeconds);
        timeLockingPeriod = _newTimeLockingPeriodInSeconds;
    }

    function mint(address _user, uint256 _tokenAmount) public onlyTradeEngine {
        if(mintingLimit == 0 || _tokenAmount <= mintingLimit) {
            state.mint(_user, _tokenAmount);
        } else {
            escrowedTokens[_user] = escrowedTokens[_user].add(_tokenAmount);
            lockedUntil[_user] = block.timestamp + timeLockingPeriod;
            emit MintingEscrowed(_user, _tokenAmount);
        }
    }

    function delayedMint(address _user) public {
        require(lockedUntil[_user] <= block.timestamp, "MorpherMintingLimiter: Funds are still time locked");
        uint256 sendAmount = escrowedTokens[_user];
        escrowedTokens[_user] = 0;
        state.mint(_user, sendAmount);
        emit EscrowReleased(_user, sendAmount);
    }

    function adminApprovedMint(address _user, uint256 _tokenAmount) public onlyAdministrator {
        escrowedTokens[_user] = escrowedTokens[_user].sub(_tokenAmount);
        state.mint(_user, _tokenAmount);
        emit EscrowReleased(_user, _tokenAmount);
    }

    function adminDisapproveMint(address _user, uint256 _tokenAmount) public onlyAdministrator {
        escrowedTokens[_user] = escrowedTokens[_user].sub(_tokenAmount);
        emit MintingDenied(_user, _tokenAmount);
    }
}

File 8 of 13: MorpherOracle.sol
pragma solidity 0.5.16;

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

// ----------------------------------------------------------------------------------
// Morpher Oracle contract v 2.0
// 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;
    MorpherState state; // read only, Oracle doesn't need writing access to state

    using SafeMath for uint256;

    bool public paused;
    bool public useWhiteList; //always false at the moment

    uint256 public gasForCallback;

    address payable public callBackCollectionAddress;

    mapping(address => bool) public callBackAddress;
    mapping(address => bool) public whiteList;
    
    mapping(bytes32 => uint256) public priceBelow;
    mapping(bytes32 => uint256) public priceAbove;
    mapping(bytes32 => uint256) public goodFrom;
    mapping(bytes32 => uint256) public goodUntil;

    mapping(bytes32 => bool) public orderCancellationRequested;

    mapping(bytes32 => address) public orderIdTradeEngineAddress;
    address public previousTradeEngineAddress;
    address public previousOracleAddress;

// ----------------------------------------------------------------------------------
// Events
// ----------------------------------------------------------------------------------
    event OrderCreated(
        bytes32 indexed _orderId,
        address indexed _address,
        bytes32 indexed _marketId,
        uint256 _closeSharesAmount,
        uint256 _openMPHTokenAmount,
        bool _tradeDirection,
        uint256 _orderLeverage,
        uint256 _onlyIfPriceBelow,
        uint256 _onlyIfPriceAbove,
        uint256 _goodFrom,
        uint256 _goodUntil
        );

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

        );

    event OrderProcessed(
        bytes32 indexed _orderId,
        uint256 _price,
        uint256 _unadjustedMarketPrice,
        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,
        uint256 _closeSharesAmount,
        uint256 _openMPHTokenAmount,
        bool _tradeDirection,
        uint256 _orderLeverage,
        uint256 _onlyIfPriceBelow,
        uint256 _onlyIfPriceAbove,
        uint256 _goodFrom,
        uint256 _goodUntil
        );

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

    event OrderCancellationRequestedEvent(
        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
        );

    event LinkMorpherState(
        address _address
        );

    event SetUseWhiteList(
        bool _useWhiteList
        );

    event AddressWhiteListed(
        address _address
        );

    event AddressBlackListed(
        address _address
        );

    event AdminLiquidationOrderCreated(
        bytes32 indexed _orderId,
        address indexed _address,
        bytes32 indexed _marketId,
        uint256 _closeSharesAmount,
        uint256 _openMPHTokenAmount,
        bool _tradeDirection,
        uint256 _orderLeverage
        );

    /**
     * Delisting markets is a function that stops when gas is running low
     * if it reached all positions it will emit "DelistMarketComplete"
     * otherwise it needs to be re-run.
     */
    event DelistMarketIncomplete(bytes32 _marketId, uint256 _processedUntilIndex);
    event DelistMarketComplete(bytes32 _marketId);
    event LockedPriceForClosingPositions(bytes32 _marketId, uint256 _price);


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

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

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

   constructor(address _tradeEngineAddress, address _morpherState, address _callBackAddress, address payable _gasCollectionAddress, uint256 _gasForCallback, address _coldStorageOwnerAddress, address _previousTradeEngineAddress, address _previousOracleAddress) public {
        setTradeEngineAddress(_tradeEngineAddress);
        setStateAddress(_morpherState);
        enableCallbackAddress(_callBackAddress);
        setCallbackCollectionAddress(_gasCollectionAddress);
        setGasForCallback(_gasForCallback);
        transferOwnership(_coldStorageOwnerAddress);
        previousTradeEngineAddress = _previousTradeEngineAddress; //that is the address before updating the trade engine. Can set to 0x0000 if a completely new deployment happens. It is only valid when mid-term updating the tradeengine
        previousOracleAddress = _previousOracleAddress; //if we are updating the oracle, then this is the previous oracle address. Can be set to 0x00 if a completely new deployment happens.
    }

// ----------------------------------------------------------------------------------
// 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 setStateAddress(address _address) public onlyOwner {
        state = MorpherState(_address);
        emit LinkMorpherState(_address);
    }

    function overrideGasForCallback(uint256 _gasForCallback) public onlyOwner {
        gasForCallback = _gasForCallback;
        emit SetGasForCallback(_gasForCallback);
    }
    
    function setGasForCallback(uint256 _gasForCallback) private {
        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);
    }

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

// ----------------------------------------------------------------------------------
// Oracle Owner can use a whitelist and authorize individual addresses
// ----------------------------------------------------------------------------------
    function setUseWhiteList(bool _useWhiteList) public onlyOracleOperator {
        require(false, "MorpherOracle: Cannot use this functionality in the oracle at the moment");
        useWhiteList = _useWhiteList;
        emit SetUseWhiteList(_useWhiteList);
    }

    function setWhiteList(address _whiteList) public onlyOracleOperator {
        whiteList[_whiteList] = true;
        emit AddressWhiteListed(_whiteList);
    }

    function setBlackList(address _blackList) public onlyOracleOperator {
        whiteList[_blackList] = false;
        emit AddressBlackListed(_blackList);
    }

    function isWhiteListed(address _address) public view returns (bool _whiteListed) {
        if (useWhiteList == false ||  whiteList[_address] == true) {
            _whiteListed = true;
        }
        return(_whiteListed);
    }

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

// ----------------------------------------------------------------------------------
// 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,
        uint256 _closeSharesAmount,
        uint256 _openMPHTokenAmount,
        bool _tradeDirection,
        uint256 _orderLeverage,
        uint256 _onlyIfPriceAbove,
        uint256 _onlyIfPriceBelow,
        uint256 _goodUntil,
        uint256 _goodFrom
        ) public payable notPaused returns (bytes32 _orderId) {
        require(isWhiteListed(msg.sender),"MorpherOracle: Address not eligible to create an order.");
        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, _closeSharesAmount, _openMPHTokenAmount, _tradeDirection, _orderLeverage);
        orderIdTradeEngineAddress[_orderId] = address(tradeEngine);

        //if the market was deactivated, and the trader didn't fail yet, then we got an orderId to close the position with a locked in price
        if(state.getMarketActive(_marketId) == false) {

            //price will come from the position where price is stored forever
            tradeEngine.processOrder(_orderId, tradeEngine.getDeactivatedMarketPrice(_marketId), 0, 0, now.mul(1000));
            
            emit OrderProcessed(
                _orderId,
                tradeEngine.getDeactivatedMarketPrice(_marketId),
                0,
                0,
                0,
                now.mul(1000),
                0,
                0,
                0,
                0,
                0,
                0
                );
        } else {
            priceAbove[_orderId] = _onlyIfPriceAbove;
            priceBelow[_orderId] = _onlyIfPriceBelow;
            goodFrom[_orderId]   = _goodFrom;
            goodUntil[_orderId]  = _goodUntil;
            emit OrderCreated(
                _orderId,
                msg.sender,
                _marketId,
                _closeSharesAmount,
                _openMPHTokenAmount,
                _tradeDirection,
                _orderLeverage,
                _onlyIfPriceBelow,
                _onlyIfPriceAbove,
                _goodFrom,
                _goodUntil
                );
        }

        return _orderId;
    }

    function getTradeEngineFromOrderId(bytes32 _orderId) public view returns (address) {
        //get the current trade engine
        if(orderIdTradeEngineAddress[_orderId] != address(0)){
            return orderIdTradeEngineAddress[_orderId];
        }

        //todo for later
        //we can't do recursively call the oracle.getTradeEngineFromOrderId here, because the previously deployed oracle
        //doesn't have this function yet. We can uncomment this in later updates of the oracle
        // if(previousOracleAddress !== address(0)) {
        //     MorpherOracle _oracle = MorpherOracle(previousOracleAddress)
        //     return _oracle.getTradeEngineFromOrderId(_orderId);
        // }

        //nothing in there, take the previous tradeEngine then.
        return previousTradeEngineAddress;
    }

    function initiateCancelOrder(bytes32 _orderId) public {
        MorpherTradeEngine _tradeEngine = MorpherTradeEngine(getTradeEngineFromOrderId(_orderId));
        require(orderCancellationRequested[_orderId] == false, "MorpherOracle: Order was already canceled.");
        (address userId, , , , , , ) = _tradeEngine.getOrder(_orderId);
        require(userId == msg.sender, "MorpherOracle: Only the user can request an order cancellation.");
        orderCancellationRequested[_orderId] = true;
        emit OrderCancellationRequestedEvent(_orderId, msg.sender);

    }
    // ----------------------------------------------------------------------------------
    // cancelOrder(bytes32  _orderId)
    // User or Administrator can cancel their own orders before the _callback has been executed
    // ----------------------------------------------------------------------------------
    function cancelOrder(bytes32 _orderId) public onlyOracleOperator {
        require(orderCancellationRequested[_orderId] == true, "MorpherOracle: Order-Cancellation was not requested.");
        MorpherTradeEngine _tradeEngine = MorpherTradeEngine(getTradeEngineFromOrderId(_orderId));
        (address userId, , , , , , ) = _tradeEngine.getOrder(_orderId);
        _tradeEngine.cancelOrder(_orderId, userId);
        clearOrderConditions(_orderId);
        emit OrderCancelled(
            _orderId,
            userId,
            msg.sender
            );
    }
    
    // ----------------------------------------------------------------------------------
    // adminCancelOrder(bytes32  _orderId)
    // Administrator can cancel before the _callback has been executed to provide an updateOrder functionality
    // ----------------------------------------------------------------------------------
    function adminCancelOrder(bytes32 _orderId) public onlyOracleOperator {
        MorpherTradeEngine _tradeEngine = MorpherTradeEngine(getTradeEngineFromOrderId(_orderId));
        (address userId, , , , , , ) = _tradeEngine.getOrder(_orderId);
        _tradeEngine.cancelOrder(_orderId, userId);
        clearOrderConditions(_orderId);
        emit AdminOrderCancelled(
            _orderId,
            userId,
            msg.sender
            );
    }

    function getGoodUntil(bytes32 _orderId) public view returns(uint) {
        if(goodUntil[_orderId] > 0) {
            return goodUntil[_orderId];
        }

        //just return the old one
        if(previousOracleAddress != address(0)) {
            MorpherOracle _oldOracle = MorpherOracle(previousOracleAddress);
            return _oldOracle.goodUntil(_orderId);
        }

        return 0;
    }
    function getGoodFrom(bytes32 _orderId) public view returns(uint) {
        if(goodFrom[_orderId] > 0) {
            return goodFrom[_orderId];
        }

        //just return the old one
        if(previousOracleAddress != address(0)) {
            MorpherOracle _oldOracle = MorpherOracle(previousOracleAddress);
            return _oldOracle.goodFrom(_orderId);
        }
        return 0;
    }
    function getPriceAbove(bytes32 _orderId) public view returns(uint) {
        if(priceAbove[_orderId] > 0) {
            return priceAbove[_orderId];
        }

        //just return the old one
        if(previousOracleAddress != address(0)) {
            MorpherOracle _oldOracle = MorpherOracle(previousOracleAddress);
            return _oldOracle.priceAbove(_orderId);
        }
        return 0;
    }
    function getPriceBelow(bytes32 _orderId) public view returns(uint) {
        if(priceBelow[_orderId] > 0) {
            return priceBelow[_orderId];
        }

        //just return the old one
        if(previousOracleAddress != address(0)) {
            MorpherOracle _oldOracle = MorpherOracle(previousOracleAddress);
            return _oldOracle.priceBelow(_orderId);
        }
        return 0;
    }

// ------------------------------------------------------------------------
// checkOrderConditions(bytes32 _orderId, uint256 _price)
// Checks if callback satisfies the order conditions
// ------------------------------------------------------------------------
    function checkOrderConditions(bytes32 _orderId, uint256 _price) public view returns (bool _conditionsMet) {
        _conditionsMet = true;
        if (now > getGoodUntil(_orderId) && getGoodUntil(_orderId) > 0) {
            _conditionsMet = false;
        }
        if (now < getGoodFrom(_orderId) && getGoodFrom(_orderId) > 0) {
            _conditionsMet = false;
        }

        if(getPriceAbove(_orderId) > 0 && getPriceBelow(_orderId) > 0) {
            if(_price < getPriceAbove(_orderId) && _price > getPriceBelow(_orderId)) {
                _conditionsMet = false;
            }
        } else {
            if (_price < getPriceAbove(_orderId) && getPriceAbove(_orderId) > 0) {
                _conditionsMet = false;
            }
            if (_price > getPriceBelow(_orderId) && getPriceBelow(_orderId) > 0) {
                _conditionsMet = false;
            }
        }
        
        return _conditionsMet;
    }

// ----------------------------------------------------------------------------------
// Deletes parameters of cancelled or processed orders
// ----------------------------------------------------------------------------------
    function clearOrderConditions(bytes32 _orderId) internal {
        priceAbove[_orderId] = 0;
        priceBelow[_orderId] = 0;
        goodFrom[_orderId]   = 0;
        goodUntil[_orderId]  = 0;
    }

// ----------------------------------------------------------------------------------
// Pausing/unpausing 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 onlyOracleOperator 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, 0, 0, true, 10**8);
        orderIdTradeEngineAddress[_orderId] = address(tradeEngine);
        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 _unadjustedMarketPrice,
        uint256 _spread,
        uint256 _liquidationTimestamp,
        uint256 _timeStamp,
        uint256 _gasForNextCallback
        ) public onlyOracleOperator notPaused returns (uint256 _newLongShares, uint256 _newShortShares, uint256 _newMeanEntry, uint256 _newMeanSpread, uint256 _newMeanLeverage, uint256 _liquidationPrice)  {
        
        require(checkOrderConditions(_orderId, _price), 'MorpherOracle Error: Order Conditions are not met');
       
       MorpherTradeEngine _tradeEngine = MorpherTradeEngine(getTradeEngineFromOrderId(_orderId));
        (
            _newLongShares,
            _newShortShares,
            _newMeanEntry,
            _newMeanSpread,
            _newMeanLeverage,
            _liquidationPrice
        ) = _tradeEngine.processOrder(_orderId, _price, _spread, _liquidationTimestamp, _timeStamp);
        
        clearOrderConditions(_orderId);
        emit OrderProcessed(
            _orderId,
            _price,
            _unadjustedMarketPrice,
            _spread,
            _liquidationTimestamp,
            _timeStamp,
            _newLongShares,
            _newShortShares,
            _newMeanEntry,
            _newMeanSpread,
            _newMeanLeverage,
            _liquidationPrice
            );
        setGasForCallback(_gasForNextCallback);
        return (_newLongShares, _newShortShares, _newMeanEntry, _newMeanSpread, _newMeanLeverage, _liquidationPrice);
    }

// ----------------------------------------------------------------------------------
// delistMarket(bytes32 _marketId)
// Administrator closes out all existing positions on _marketId market at current prices
// ----------------------------------------------------------------------------------

    uint delistMarketFromIx = 0;
    function delistMarket(bytes32 _marketId, bool _startFromScratch) public onlyAdministrator {
        require(state.getMarketActive(_marketId) == true, "Market must be active to process position liquidations.");
        // If no _fromIx and _toIx specified, do entire _list
        if (_startFromScratch) {
            delistMarketFromIx = 0;
        }
        
        uint _toIx = state.getMaxMappingIndex(_marketId);
        
        address _address;
        for (uint256 i = delistMarketFromIx; i <= _toIx; i++) {
             if(gasleft() < 250000 && i != _toIx) { //stop if there's not enough gas to write the next transaction
                delistMarketFromIx = i;
                emit DelistMarketIncomplete(_marketId, _toIx);
                return;
            } 
            
            _address = state.getExposureMappingAddress(_marketId, i);
            adminLiquidationOrder(_address, _marketId);
            
        }
        emit DelistMarketComplete(_marketId);
    }

    /**
     * Course of action would be:
     * 1. de-activate market through state
     * 2. set the Deactivated Market Price
     * 3. let users still close their positions
     */
    function setDeactivatedMarketPrice(bytes32 _marketId, uint256 _price) public onlyAdministrator {
        //todo updateable tradeEngine
        tradeEngine.setDeactivatedMarketPrice(_marketId, _price);
        emit LockedPriceForClosingPositions(_marketId, _price);

    }

// ----------------------------------------------------------------------------------
// adminLiquidationOrder(address _address, bytes32 _marketId)
// Administrator closes out an existing position of _address on _marketId market at current price
// ----------------------------------------------------------------------------------
    function adminLiquidationOrder(
        address _address,
        bytes32 _marketId
        ) public onlyAdministrator returns (bytes32 _orderId) {
            uint256 _positionLongShares = state.getLongShares(_address, _marketId);
            uint256 _positionShortShares = state.getShortShares(_address, _marketId);
            if (_positionLongShares > 0) {
                _orderId = tradeEngine.requestOrderId(_address, _marketId, _positionLongShares, 0, false, 10**8);
                emit AdminLiquidationOrderCreated(_orderId, _address, _marketId, _positionLongShares, 0, false, 10**8);
            }
            if (_positionShortShares > 0) {
                _orderId = tradeEngine.requestOrderId(_address, _marketId, _positionShortShares, 0, true, 10**8);
                emit AdminLiquidationOrderCreated(_orderId, _address, _marketId, _positionShortShares, 0, true, 10**8);
            }
            orderIdTradeEngineAddress[_orderId] = address(tradeEngine);
            return _orderId;
    }
    
// ----------------------------------------------------------------------------------
// 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 9 of 13: MorpherStaking.sol
pragma solidity 0.5.16;

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

// ----------------------------------------------------------------------------------
// Staking Morpher Token generates interest
// The interest is set to 0.015% a day or ~5.475% in the first year
// Stakers will be able to vote on all ProtocolDecisions in MorpherGovernance (soon...)
// There is a lockup after staking or topping up (30 days) and a minimum stake (100k MPH)
// ----------------------------------------------------------------------------------

contract MorpherStaking is Ownable {
    using SafeMath for uint256;
    IMorpherState state;

    uint256 constant PRECISION = 10**8;
    uint256 constant INTERVAL  = 1 days;

    //mapping(address => uint256) private poolShares;
    //mapping(address => uint256) private lockup;

    uint256 public poolShareValue = PRECISION;
    uint256 public lastReward;
    uint256 public totalShares;
    uint256 public interestRate = 15000; // 0.015% per day initially, diminishing returns over time
    uint256 public lockupPeriod = 30 days; // to prevent tactical staking and ensure smooth governance
    uint256 public minimumStake = 10**23; // 100k MPH minimum

    address public stakingAdmin;

    address public stakingAddress = 0x2222222222222222222222222222222222222222;
    bytes32 public marketIdStakingMPH = 0x9a31fdde7a3b1444b1befb10735dcc3b72cbd9dd604d2ff45144352bf0f359a6; //STAKING_MPH

// ----------------------------------------------------------------------------
// Events
// ----------------------------------------------------------------------------
    event SetInterestRate(uint256 newInterestRate);
    event SetLockupPeriod(uint256 newLockupPeriod);
    event SetMinimumStake(uint256 newMinimumStake);
    event LinkState(address stateAddress);
    event SetStakingAdmin(address stakingAdmin);
    
    event PoolShareValueUpdated(uint256 indexed lastReward, uint256 poolShareValue);
    event StakingRewardsMinted(uint256 indexed lastReward, uint256 delta);
    event Staked(address indexed userAddress, uint256 indexed amount, uint256 poolShares, uint256 lockedUntil);
    event Unstaked(address indexed userAddress, uint256 indexed amount, uint256 poolShares);
    
    modifier onlyStakingAdmin {
        require(msg.sender == stakingAdmin, "MorpherStaking: can only be called by Staking Administrator.");
        _;
    }
    
    constructor(address _morpherState, address _stakingAdmin) public {
        setStakingAdmin(_stakingAdmin);
        setMorpherStateAddress(_morpherState);
        emit SetLockupPeriod(lockupPeriod);
        emit SetMinimumStake(minimumStake);
        emit SetInterestRate(interestRate);
        lastReward = now;
        // missing: transferOwnership to Governance once deployed
    }

// ----------------------------------------------------------------------------
// updatePoolShareValue
// Updates the value of the Pool Shares and returns the new value.
// Staking rewards are linear, there is no compound interest.
// ----------------------------------------------------------------------------
    
    function updatePoolShareValue() public returns (uint256 _newPoolShareValue) {
        if (now >= lastReward.add(INTERVAL)) {
            uint256 _numOfIntervals = now.sub(lastReward).div(INTERVAL);
            poolShareValue = poolShareValue.add(_numOfIntervals.mul(interestRate));
            lastReward = lastReward.add(_numOfIntervals.mul(INTERVAL));
            emit PoolShareValueUpdated(lastReward, poolShareValue);
        }
        mintStakingRewards();
        return poolShareValue;        
    }

// ----------------------------------------------------------------------------
// Staking rewards are minted if necessary
// ----------------------------------------------------------------------------

    function mintStakingRewards() private {
        uint256 _targetBalance = poolShareValue.mul(totalShares);
        if (state.balanceOf(stakingAddress) < _targetBalance) {
            // If there are not enough token held by the contract, mint them
            uint256 _delta = _targetBalance.sub(state.balanceOf(stakingAddress));
            state.mint(stakingAddress, _delta);
            emit StakingRewardsMinted(lastReward, _delta);
        }
    }

// ----------------------------------------------------------------------------
// stake(uint256 _amount)
// User specifies an amount they intend to stake. Pool Shares are issued accordingly
// and the _amount is transferred to the staking contract
// ----------------------------------------------------------------------------

    function stake(uint256 _amount) public returns (uint256 _poolShares) {
        require(state.balanceOf(msg.sender) >= _amount, "MorpherStaking: insufficient MPH token balance");
        updatePoolShareValue();
        _poolShares = _amount.div(poolShareValue);
        (uint256 _numOfShares, , , , , ) = state.getPosition(msg.sender, marketIdStakingMPH);
        require(minimumStake <= _numOfShares.add(_poolShares).mul(poolShareValue), "MorpherStaking: stake amount lower than minimum stake");
        state.transfer(msg.sender, stakingAddress, _poolShares.mul(poolShareValue));
        totalShares = totalShares.add(_poolShares);
        state.setPosition(msg.sender, marketIdStakingMPH, now.add(lockupPeriod), _numOfShares.add(_poolShares), 0, 0, 0, 0, 0);
        emit Staked(msg.sender, _amount, _poolShares, now.add(lockupPeriod));
        return _poolShares;
    }

// ----------------------------------------------------------------------------
// unstake(uint256 _amount)
// User specifies number of Pool Shares they want to unstake. 
// Pool Shares get deleted and the user receives their MPH plus interest
// ----------------------------------------------------------------------------

    function unstake(uint256 _numOfShares) public returns (uint256 _amount) {
        (uint256 _numOfExistingShares, , , , , ) = state.getPosition(msg.sender, marketIdStakingMPH);
        require(_numOfShares <= _numOfExistingShares, "MorpherStaking: insufficient pool shares");

        uint256 lockedInUntil = state.getLastUpdated(msg.sender, marketIdStakingMPH);
        require(now >= lockedInUntil, "MorpherStaking: cannot unstake before lockup expiration");
        updatePoolShareValue();
        state.setPosition(msg.sender, marketIdStakingMPH, lockedInUntil, _numOfExistingShares.sub(_numOfShares), 0, 0, 0, 0, 0);
        totalShares = totalShares.sub(_numOfShares);
        _amount = _numOfShares.mul(poolShareValue);
        state.transfer(stakingAddress, msg.sender, _amount);
        emit Unstaked(msg.sender, _amount, _numOfShares);
        return _amount;
    }

// ----------------------------------------------------------------------------
// Administrative functions
// ----------------------------------------------------------------------------

    function setStakingAdmin(address _address) public onlyOwner {
        stakingAdmin = _address;
        emit SetStakingAdmin(_address);
    }

    function setMorpherStateAddress(address _stateAddress) public onlyOwner {
        state = IMorpherState(_stateAddress);
        emit LinkState(_stateAddress);
    }

    function setInterestRate(uint256 _interestRate) public onlyStakingAdmin {
        interestRate = _interestRate;
        emit SetInterestRate(_interestRate);
    }

    function setLockupPeriodRate(uint256 _lockupPeriod) public onlyStakingAdmin {
        lockupPeriod = _lockupPeriod;
        emit SetLockupPeriod(_lockupPeriod);
    }
    
    function setMinimumStake(uint256 _minimumStake) public onlyStakingAdmin {
        minimumStake = _minimumStake;
        emit SetMinimumStake(_minimumStake);
    }

// ----------------------------------------------------------------------------
// Getter functions
// ----------------------------------------------------------------------------

    function getTotalPooledValue() public view returns (uint256 _totalPooled) {
        // Only accurate if poolShareValue is up to date
        return poolShareValue.mul(totalShares);
    }

    function getStake(address _address) public view returns (uint256 _poolShares) {
        (uint256 _numOfShares, , , , , ) = state.getPosition(_address, marketIdStakingMPH);
        return _numOfShares;
    }

    function getStakeValue(address _address) public view returns(uint256 _value, uint256 _lastUpdate) {
        // Only accurate if poolShareValue is up to date
        
        (uint256 _numOfShares, , , , , ) = state.getPosition(_address, marketIdStakingMPH);

        return (_numOfShares.mul(poolShareValue), lastReward);
    }
    
// ------------------------------------------------------------------------
// Don't accept ETH
// ------------------------------------------------------------------------

    function () external payable {
        revert("MorpherStaking: you can't deposit Ether here");
    }
}

File 10 of 13: 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(address sender) {
        require(getCanTransfer(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);
        
        administrator = owner(); //first set the owner as administrator
        morpherGovernance = owner(); //first set the owner as governance
        
        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 onlyGovernance {
        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 onlyAdministrator {
        stateAccess[_address] = true;
        emit StateAccessGranted(_address, block.number);
    }

    function denyAccess(address _address) public onlyAdministrator {
        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 onlyAdministrator {
        transferAllowed[_address] = true;
        emit TransfersEnabled(_address);
    }

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

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

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

    function transfer(address _from, address _to, uint256 _token) public onlyPlatform notPaused canTransfer(_from) {
        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 onlyGovernance {
        morpherGovernance = _newGovernanceContractAddress;
        emit GovernanceChange(_newGovernanceContractAddress);
    }

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

    function setMorpherBridge(address _newBridge) public onlyGovernance {
        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 onlyGovernance {
        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 onlyGovernance {
        morpherRewards = _newRewardsAddress;
        emit RewardsChange(_newRewardsAddress, rewardBasisPoints);
    }

    function setRewardBasisPoints(uint256 _newRewardBasisPoints) public onlyGovernance {
        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 onlyAdministrator {
        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 11 of 13: 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.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 12 of 13: 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 13 of 13: 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

API
[{"inputs":[{"internalType":"address","name":"_stateAddress","type":"address"},{"internalType":"address","name":"_coldStorageOwnerAddress","type":"address"},{"internalType":"address","name":"_stakingContractAddress","type":"address"},{"internalType":"bool","name":"_escrowOpenOrderEnabled","type":"bool"},{"internalType":"uint256","name":"_deployedTimestampOverride","type":"uint256"},{"internalType":"address","name":"_mintingLimiterAddress","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_mintingLimiterAddress","type":"address"}],"name":"LinkMintingLimiter","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_stakingAddress","type":"address"}],"name":"LinkStaking","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_address","type":"address"}],"name":"LinkState","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_price","type":"uint256"}],"name":"LockedPriceForClosingPositions","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"_orderId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"_address","type":"address"}],"name":"OrderCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"_orderId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"_address","type":"address"},{"indexed":true,"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_closeSharesAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_openMPHTokenAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"_tradeDirection","type":"bool"},{"indexed":false,"internalType":"uint256","name":"_orderLeverage","type":"uint256"}],"name":"OrderIdRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"_orderId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_marketPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_marketSpread","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_liquidationTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_timeStamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newLongShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newShortShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newAverageEntry","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newAverageSpread","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newAverageLeverage","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_liquidationPrice","type":"uint256"}],"name":"OrderProcessed","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":"_address","type":"address"},{"indexed":true,"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"_longPosition","type":"bool"},{"indexed":false,"internalType":"uint256","name":"_timeStamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_marketPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_marketSpread","type":"uint256"}],"name":"PositionLiquidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_userId","type":"address"},{"indexed":false,"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_timeStamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newLongShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newShortShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newMeanEntryPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newMeanEntrySpread","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newMeanEntryLeverage","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newLiquidationPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_mint","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_burn","type":"uint256"}],"name":"PositionUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"_orderId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"oldTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTimestamp","type":"uint256"}],"name":"ResetTimestampInOrder","type":"event"},{"constant":true,"inputs":[],"name":"_owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_averagePrice","type":"uint256"},{"internalType":"uint256","name":"_averageLeverage","type":"uint256"},{"internalType":"uint256","name":"_positionTimeStampInMs","type":"uint256"}],"name":"calculateMarginInterest","outputs":[{"internalType":"uint256","name":"_marginInterest","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_orderId","type":"bytes32"},{"internalType":"address","name":"_address","type":"address"}],"name":"cancelOrder","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"closedMarketPriceLock","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_orderId","type":"bytes32"}],"name":"computeLiquidationPrice","outputs":[{"internalType":"uint256","name":"_liquidationPrice","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"deployedTimeStamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"escrowOpenOrderAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"escrowOpenOrderEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getAdministrator","outputs":[{"internalType":"address","name":"_administrator","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getDeactivatedMarketPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_newMeanEntryPrice","type":"uint256"},{"internalType":"uint256","name":"_newMeanEntryLeverage","type":"uint256"},{"internalType":"bool","name":"_long","type":"bool"},{"internalType":"uint256","name":"_positionTimestampInMs","type":"uint256"}],"name":"getLiquidationPrice","outputs":[{"internalType":"uint256","name":"_liquidationPrice","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"_orderId","type":"bytes32"}],"name":"getOrder","outputs":[{"internalType":"address","name":"_userId","type":"address"},{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"uint256","name":"_closeSharesAmount","type":"uint256"},{"internalType":"uint256","name":"_openMPHTokenAmount","type":"uint256"},{"internalType":"uint256","name":"_marketPrice","type":"uint256"},{"internalType":"uint256","name":"_marketSpread","type":"uint256"},{"internalType":"uint256","name":"_orderLeverage","type":"uint256"}],"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":"_positionLongShares","type":"uint256"},{"internalType":"uint256","name":"_positionShortShares","type":"uint256"},{"internalType":"uint256","name":"_positionAveragePrice","type":"uint256"},{"internalType":"uint256","name":"_positionAverageSpread","type":"uint256"},{"internalType":"uint256","name":"_positionAverageLeverage","type":"uint256"},{"internalType":"uint256","name":"_liquidationPrice","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastOrderId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_positionAveragePrice","type":"uint256"},{"internalType":"uint256","name":"_positionAverageLeverage","type":"uint256"},{"internalType":"uint256","name":"_positionTimeStampInMs","type":"uint256"},{"internalType":"uint256","name":"_marketPrice","type":"uint256"},{"internalType":"uint256","name":"_marketSpread","type":"uint256"},{"internalType":"uint256","name":"_orderLeverage","type":"uint256"},{"internalType":"bool","name":"_sell","type":"bool"}],"name":"longShareValue","outputs":[{"internalType":"uint256","name":"_shareValue","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"orderNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":[{"internalType":"bytes32","name":"_orderId","type":"bytes32"},{"internalType":"uint256","name":"_marketPrice","type":"uint256"},{"internalType":"uint256","name":"_marketSpread","type":"uint256"},{"internalType":"uint256","name":"_liquidationTimestamp","type":"uint256"},{"internalType":"uint256","name":"_timeStampInMS","type":"uint256"}],"name":"processOrder","outputs":[{"internalType":"uint256","name":"_newLongShares","type":"uint256"},{"internalType":"uint256","name":"_newShortShares","type":"uint256"},{"internalType":"uint256","name":"_newAverageEntry","type":"uint256"},{"internalType":"uint256","name":"_newAverageSpread","type":"uint256"},{"internalType":"uint256","name":"_newAverageLeverage","type":"uint256"},{"internalType":"uint256","name":"_liquidationPrice","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","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":"_closeSharesAmount","type":"uint256"},{"internalType":"uint256","name":"_openMPHTokenAmount","type":"uint256"},{"internalType":"bool","name":"_tradeDirection","type":"bool"},{"internalType":"uint256","name":"_orderLeverage","type":"uint256"}],"name":"requestOrderId","outputs":[{"internalType":"bytes32","name":"_orderId","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"setDeactivatedMarketPrice","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bool","name":"_isEnabled","type":"bool"}],"name":"setEscrowOpenOrderEnabled","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_mintingLimiterAddress","type":"address"}],"name":"setMorpherMintingLimiter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_stakingAddress","type":"address"}],"name":"setMorpherStaking","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_stateAddress","type":"address"}],"name":"setMorpherState","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_positionAveragePrice","type":"uint256"},{"internalType":"uint256","name":"_positionAverageLeverage","type":"uint256"},{"internalType":"uint256","name":"_positionTimeStampInMs","type":"uint256"},{"internalType":"uint256","name":"_marketPrice","type":"uint256"},{"internalType":"uint256","name":"_marketSpread","type":"uint256"},{"internalType":"uint256","name":"_orderLeverage","type":"uint256"},{"internalType":"bool","name":"_sell","type":"bool"}],"name":"shortShareValue","outputs":[{"internalType":"uint256","name":"_shareValue","type":"uint256"}],"payable":false,"stateMutability":"view","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":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]

6080604052600780546001600160a01b0319908116731111111111111111111111111111111111111111179091556008805490911660011790553480156200004657600080fd5b506040516200609438038062006094833981810160405260c08110156200006c57600080fd5b50805160208201516040808401516060850151608086015160a090960151600080546001600160a01b031916331780825594519697959693959294929391926001600160a01b03169160008051602062006054833981519152908290a3620000dd866001600160e01b036200014f16565b620000f1846001600160e01b03620001f716565b62000105816001600160e01b036200029f16565b62000119856001600160e01b036200034716565b6007805460ff60a01b1916600160a01b85151502179055816200013d57426200013f565b815b6006555062000454945050505050565b620001626001600160e01b03620003b216565b620001a3576040805162461bcd60e51b8152602060048201819052602482015260008051602062006074833981519152604482015290519081900360640190fd5b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f978c711532bae8c58f353b0f3c7f3a0dfe600d9ae9a81818f2ad2919b88e19909181900360200190a150565b6200020a6001600160e01b03620003b216565b6200024b576040805162461bcd60e51b8152602060048201819052602482015260008051602062006074833981519152604482015290519081900360640190fd5b600280546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4016bbc93bb2adf11f6d1b2509a1ab5f593cbe26e54875655329f9c80117f0849181900360200190a150565b620002b26001600160e01b03620003b216565b620002f3576040805162461bcd60e51b8152602060048201819052602482015260008051602062006074833981519152604482015290519081900360640190fd5b600380546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f42c6bffb0e058cc1dfabd910037516fb01b87949d9a476876ff43179d62f4dc89181900360200190a150565b6200035a6001600160e01b03620003b216565b6200039b576040805162461bcd60e51b8152602060048201819052602482015260008051602062006074833981519152604482015290519081900360640190fd5b620003af816001600160e01b03620003c316565b50565b6000546001600160a01b0316331490565b6001600160a01b0381166200040a5760405162461bcd60e51b81526004018080602001828103825260288152602001806200602c6028913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216916000805160206200605483398151915291a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b615bc880620004646000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c8063715018a611610104578063ac8f6f7f116100a2578063daf9502711610071578063daf9502714610575578063dc39d06d1461059b578063f2fde38b146105c7578063f40b7b32146105ed576101cf565b8063ac8f6f7f146104dc578063ac9eee2814610522578063b2bdfa7b14610541578063d61aed7a14610549576101cf565b806380104668116100de57806380104668146104895780638da5cb5b146104af5780638f32d59b146104b7578063a386fb56146104bf576101cf565b8063715018a61461042a5780637993a991146104325780637dffd04014610458576101cf565b80634702513c116101715780635778472a1161014b5780635778472a146103755780636950baa8146103d45780636b4f7065146103dc5780637023b78314610405576101cf565b80634702513c1461030d578063480ee2071461032a5780635662ecc71461036d576101cf565b806316f77a5b116101ad57806316f77a5b1461027357806316f8de89146102a857806323aab432146102c25780633754c565146102ca576101cf565b80630fa8f516146101d457806316194bac14610233578063169674071461024f575b600080fd5b610200600480360360408110156101ea57600080fd5b506001600160a01b0381351690602001356105f5565b604080519687526020870195909552858501939093526060850191909152608084015260a0830152519081900360c00190f35b61023b610942565b604080519115158252519081900360200190f35b610257610952565b604080516001600160a01b039092168252519081900360200190f35b610200600480360360a081101561028957600080fd5b50803590602081013590604081013590606081013590608001356109c8565b6102b0611176565b60408051918252519081900360200190f35b61025761117c565b6102b0600480360360e08110156102e057600080fd5b5080359060208101359060408101359060608101359060808101359060a08101359060c00135151561118b565b6102b06004803603602081101561032357600080fd5b50356112c1565b6102b0600480360360e081101561034057600080fd5b5080359060208101359060408101359060608101359060808101359060a08101359060c001351515611389565b6102b061140c565b6103926004803603602081101561038b57600080fd5b5035611412565b604080516001600160a01b0390981688526020880196909652868601949094526060860192909252608085015260a084015260c0830152519081900360e00190f35b610257611459565b6102b0600480360360608110156103f257600080fd5b5080359060208101359060400135611468565b6104286004803603604081101561041b57600080fd5b50803590602001356115a5565b005b610428611765565b6104286004803603602081101561044857600080fd5b50356001600160a01b03166117f6565b6102b06004803603608081101561046e57600080fd5b50803590602081013590604081013515159060600135611891565b6104286004803603602081101561049f57600080fd5b50356001600160a01b031661192b565b6102576119c6565b61023b6119d5565b6102b0600480360360208110156104d557600080fd5b50356119e6565b6102b0600480360360c08110156104f257600080fd5b506001600160a01b0381351690602081013590604081013590606081013590608081013515159060a00135611a75565b6104286004803603602081101561053857600080fd5b50351515612226565b61025761228b565b6104286004803603604081101561055f57600080fd5b50803590602001356001600160a01b031661229a565b6104286004803603602081101561058b57600080fd5b50356001600160a01b0316612517565b61023b600480360360408110156105b157600080fd5b506001600160a01b0381351690602001356125b2565b610428600480360360208110156105dd57600080fd5b50356001600160a01b0316612697565b6102b06126ea565b600154604080516377afd19160e11b81526001600160a01b03858116600483015260248201859052915160009384938493849384938493169163ef5fa322916044808301926020929190829003018186803b15801561065357600080fd5b505afa158015610667573d6000803e3d6000fd5b505050506040513d602081101561067d57600080fd5b5051600154604080516301864ba360e41b81526001600160a01b038c81166004830152602482018c905291519190921691631864ba30916044808301926020929190829003018186803b1580156106d357600080fd5b505afa1580156106e7573d6000803e3d6000fd5b505050506040513d60208110156106fd57600080fd5b50516001546040805163e291f13560e01b81526001600160a01b038d81166004830152602482018d90529151919092169163e291f135916044808301926020929190829003018186803b15801561075357600080fd5b505afa158015610767573d6000803e3d6000fd5b505050506040513d602081101561077d57600080fd5b505160015460408051633bfbb2c160e21b81526001600160a01b038e81166004830152602482018e90529151919092169163efeecb04916044808301926020929190829003018186803b1580156107d357600080fd5b505afa1580156107e7573d6000803e3d6000fd5b505050506040513d60208110156107fd57600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038f81166004830152602482018f90529151919092169163faddee14916044808301926020929190829003018186803b15801561085357600080fd5b505afa158015610867573d6000803e3d6000fd5b505050506040513d602081101561087d57600080fd5b8101908080519060200190929190505050600160009054906101000a90046001600160a01b03166001600160a01b031663652f17638e8e6040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b031681526020018281526020019250505060206040518083038186803b15801561090157600080fd5b505afa158015610915573d6000803e3d6000fd5b505050506040513d602081101561092b57600080fd5b5051949d939c50919a509850965090945092505050565b600754600160a01b900460ff1681565b60015460408051631696740760e01b815290516000926001600160a01b0316916316967407916004808301926020929190829003018186803b15801561099757600080fd5b505afa1580156109ab573d6000803e3d6000fd5b505050506040513d60208110156109c157600080fd5b5051905090565b600080600080600080600160009054906101000a90046001600160a01b03166001600160a01b031663e3bbb5656040518163ffffffff1660e01b815260040160206040518083038186803b158015610a1f57600080fd5b505afa158015610a33573d6000803e3d6000fd5b505050506040513d6020811015610a4957600080fd5b50516001600160a01b03163314610a915760405162461bcd60e51b8152600401808060200182810382526043815260200180615a386043913960600191505060405180910390fd5b60008b8152600960205260409020546001600160a01b0316610ae45760405162461bcd60e51b815260040180806020018281038252603e815260200180615919603e913960400191505060405180910390fd5b60008a11610b235760405162461bcd60e51b8152600401808060200182810382526049815260200180615b046049913960600191505060405180910390fd5b888a1015610b625760405162461bcd60e51b81526004018080602001828103825260558152602001806159c26055913960600191505060405180910390fd5b60008b815260096020818152604092839020600681018e9055600781018d90559182018a9055600582018b9055600180549201548351634a4cce9760e01b8152600481019190915292516001600160a01b0390921692634a4cce979260248083019392829003018186803b158015610bd957600080fd5b505afa158015610bed573d6000803e3d6000fd5b505050506040513d6020811015610c0357600080fd5b5051610c4057610c128b6126f0565b60008b815260096020526040902060010154610c2d906119e6565b60008c8152600960205260409020600601555b6001805460008d81526009602090815260409182902080549401548251630f5fd3cf60e21b81526001600160a01b039586166004820152602481019190915291519390921692633d7f4f3c92604480840193919291829003018186803b158015610ca957600080fd5b505afa158015610cbd573d6000803e3d6000fd5b505050506040513d6020811015610cd357600080fd5b5051881115610ce557610ce58b61272e565b610cee8b612c41565b60008b81526009602052604090206004015460ff1615610d1657610d118b612cea565b610d1f565b610d1f8b612fe0565b60008b815260096020818152604080842080546001820180546001600160a01b03198316845590879055600283018790556003830187905560048301805460ff1916905560058301879055600683018790556007830187905560088301879055948201869055600a8201869055600b8201869055600c8201869055600d8201869055600e8201869055600f82018690556010820186905560118201869055601282018690556013820186905560149091019490945580518f81529182018e90528181018d9052606082018c9052608082018b905260a082018a905260c0820189905260e08201889052610100820187905261012082018690526101408201859052516001600160a01b03909316927f696a3d28d7b4bcfc9cbfef719a03218d7a502cda20d01f9ef8086249e8165492918190036101600190a1600154604080516377afd19160e11b81526001600160a01b038581166004830152602482018590529151919092169163ef5fa322916044808301926020929190829003018186803b158015610eac57600080fd5b505afa158015610ec0573d6000803e3d6000fd5b505050506040513d6020811015610ed657600080fd5b5051600154604080516301864ba360e41b81526001600160a01b0386811660048301526024820186905291519190921691631864ba30916044808301926020929190829003018186803b158015610f2c57600080fd5b505afa158015610f40573d6000803e3d6000fd5b505050506040513d6020811015610f5657600080fd5b50516001546040805163e291f13560e01b81526001600160a01b038781166004830152602482018790529151919092169163e291f135916044808301926020929190829003018186803b158015610fac57600080fd5b505afa158015610fc0573d6000803e3d6000fd5b505050506040513d6020811015610fd657600080fd5b505160015460408051633bfbb2c160e21b81526001600160a01b038881166004830152602482018890529151919092169163efeecb04916044808301926020929190829003018186803b15801561102c57600080fd5b505afa158015611040573d6000803e3d6000fd5b505050506040513d602081101561105657600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038981166004830152602482018990529151919092169163faddee14916044808301926020929190829003018186803b1580156110ac57600080fd5b505afa1580156110c0573d6000803e3d6000fd5b505050506040513d60208110156110d657600080fd5b50516001546040805163652f176360e01b81526001600160a01b038a81166004830152602482018a90529151919092169163652f1763916044808301926020929190829003018186803b15801561112c57600080fd5b505afa158015611140573d6000803e3d6000fd5b505050506040513d602081101561115657600080fd5b5051949c50929a5090985096509450925050509550955095509550955095565b60045481565b6008546001600160a01b031681565b600087876305f5e1008110156111a257506305f5e1005b836111ad5750859050835b866111bb838360008c611891565b116111c957600092506112b4565b6111fd6305f5e1006111f16111e4828563ffffffff6132b816565b859063ffffffff61331916565b9063ffffffff61337216565b925061122761121a6305f5e1006111f18a8563ffffffff61331916565b849063ffffffff6133b416565b9250600184151514156112895761124f61121a6305f5e1006111f1898563ffffffff61331916565b9250600061125e83838b611468565b905083811161127e57611277848263ffffffff6133b416565b9350611283565b600093505b506112b4565b6112b16112a46305f5e1006111f1898963ffffffff61331916565b849063ffffffff6132b816565b92505b5050979650505050505050565b600081815260096020526040812060138101829055600e01541561132057600082815260096020819052604090912060108101546012820154919092015461130d929190600190611891565b6000838152600960205260409020601301555b6000828152600960205260409020600f01541561137357600082815260096020819052604082206010810154601282015491909201546113609390611891565b6000838152600960205260409020601301555b5060009081526009602052604090206013015490565b600087876305f5e1008110156113a057506305f5e1005b836113ab5750859050835b6113b8828260018b611891565b87116113c757600092506112b4565b6113e26305f5e1006111f16111e4848363ffffffff6133b416565b9250611227836114006305f5e1006111f18b8663ffffffff61331916565b9063ffffffff6133b416565b60055481565b60009081526009602052604090208054600182015460028301546003840154600685015460078601546008909601546001600160a01b039095169693959294919390929190565b6007546001600160a01b031681565b600654600090611480836103e863ffffffff61337216565b101561149e5760065461149b906103e863ffffffff61331916565b91505b6114b56111e4846305f5e10063ffffffff6133b416565b90506115016114f460016114e8620151806111f16114db886103e863ffffffff61337216565b429063ffffffff6133b416565b9063ffffffff6132b816565b829063ffffffff61331916565b905061159d6305f5e1006111f16305f5e1006111f1600260009054906101000a90046001600160a01b03166001600160a01b0316637c3a00fd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561156457600080fd5b505afa158015611578573d6000803e3d6000fd5b505050506040513d602081101561158e57600080fd5b5051869063ffffffff61331916565b949350505050565b600160009054906101000a90046001600160a01b03166001600160a01b031663e3bbb5656040518163ffffffff1660e01b815260040160206040518083038186803b1580156115f357600080fd5b505afa158015611607573d6000803e3d6000fd5b505050506040513d602081101561161d57600080fd5b50516001600160a01b031633146116655760405162461bcd60e51b8152600401808060200182810382526043815260200180615a386043913960600191505060405180910390fd5b6001546008546001600160a01b039182169163be7e64b6911684611691426103e863ffffffff61331916565b604080516001600160e01b031960e087901b1681526001600160a01b039094166004850152602484019290925260448301526000606483018190526084830181905260a4830186905260c4830181905260e48301819052610104830181905290516101248084019382900301818387803b15801561170e57600080fd5b505af1158015611722573d6000803e3d6000fd5b5050604080518581526020810185905281517f3cf30f15febef0d3f8e86318070db2c80d03fd14e8406d326aab41cb043f18399450908190039091019150a15050565b61176d6119d5565b6117ac576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6117fe6119d5565b61183d576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b600280546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4016bbc93bb2adf11f6d1b2509a1ab5f593cbe26e54875655329f9c80117f0849181900360200190a150565b6000600183151514156118ea576118c6846111f16118b9826305f5e10063ffffffff6133b416565b889063ffffffff61331916565b90506118e36118d6868685611468565b829063ffffffff6132b816565b905061159d565b611905846111f16118b9826305f5e10063ffffffff6132b816565b9050611922611915868685611468565b829063ffffffff6133b416565b95945050505050565b6119336119d5565b611972576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f978c711532bae8c58f353b0f3c7f3a0dfe600d9ae9a81818f2ad2919b88e19909181900360200190a150565b6000546001600160a01b031690565b6000546001600160a01b0316331490565b600154600854604080516307d47a8b60e11b81526001600160a01b03928316600482015260248101859052905160009384931691630fa8f5169160448083019260c0929190829003018186803b158015611a3f57600080fd5b505afa158015611a53573d6000803e3d6000fd5b505050506040513d60c0811015611a6957600080fd5b50604001519392505050565b6001546040805163e3bbb56560e01b815290516000926001600160a01b03169163e3bbb565916004808301926020929190829003018186803b158015611aba57600080fd5b505afa158015611ace573d6000803e3d6000fd5b505050506040513d6020811015611ae457600080fd5b50516001600160a01b03163314611b2c5760405162461bcd60e51b8152600401808060200182810382526043815260200180615a386043913960600191505060405180910390fd5b6305f5e100821015611b6f5760405162461bcd60e51b8152600401808060200182810382526041815260200180615ac36041913960600191505060405180910390fd5b600160009054906101000a90046001600160a01b03166001600160a01b0316637c995e916040518163ffffffff1660e01b815260040160206040518083038186803b158015611bbd57600080fd5b505afa158015611bd1573d6000803e3d6000fd5b505050506040513d6020811015611be757600080fd5b5051821115611c275760405162461bcd60e51b815260040180806020018281038252603e815260200180615752603e913960400191505060405180910390fd5b611c3487878787876133f6565b600160009054906101000a90046001600160a01b03166001600160a01b031663755ca87a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c8257600080fd5b505afa158015611c96573d6000803e3d6000fd5b505050506040513d6020811015611cac57600080fd5b505160015460408051631722e4cd60e21b81526001600160a01b038b8116600483015291519190921691635c8b9334916024808301926020929190829003018186803b158015611cfb57600080fd5b505afa158015611d0f573d6000803e3d6000fd5b505050506040513d6020811015611d2557600080fd5b5051111580611dad5750600154604080516330826beb60e21b81526001600160a01b038a8116600483015291514393929092169163c209afac91602480820192602092909190829003018186803b158015611d7f57600080fd5b505afa158015611d93573d6000803e3d6000fd5b505050506040513d6020811015611da957600080fd5b5051105b611de85760405162461bcd60e51b815260040180806020018281038252604a815260200180615839604a913960600191505060405180910390fd5b8315611f73578215611eb657600154604080516301864ba360e41b81526001600160a01b038a81166004830152602482018a905291519190921691631864ba30916044808301926020929190829003018186803b158015611e4857600080fd5b505afa158015611e5c573d6000803e3d6000fd5b505050506040513d6020811015611e7257600080fd5b50518514611eb15760405162461bcd60e51b815260040180806020018281038252605f8152602001806157da605f913960600191505060405180910390fd5b611f73565b600154604080516377afd19160e11b81526001600160a01b038a81166004830152602482018a90529151919092169163ef5fa322916044808301926020929190829003018186803b158015611f0a57600080fd5b505afa158015611f1e573d6000803e3d6000fd5b505050506040513d6020811015611f3457600080fd5b50518514611f735760405162461bcd60e51b815260040180806020018281038252605f8152602001806157da605f913960600191505060405180910390fd5b600154604080516303d4880760e11b81526001600160a01b038a81166004830152915191909216916307a9100e91602480830192600092919082900301818387803b158015611fc157600080fd5b505af1158015611fd5573d6000803e3d6000fd5b505060015460408051635e61f1a160e11b81526001600160a01b038c81166004830152915191909216935063bcc3e3429250602480830192600092919082900301818387803b15801561202757600080fd5b505af115801561203b573d6000803e3d6000fd5b505050506004600081548092919060010191905055508643878787878760045460405160200180896001600160a01b03166001600160a01b031660601b8152601401888152602001878152602001868152602001858152602001841515151560f81b81526001018381526020018281526020019850505050505050505060405160208183030381529060405280519060200120905080600581905550866009600083815260200190815260200160002060000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550856009600083815260200190815260200160002060010181905550846009600083815260200190815260200160002060020181905550836009600083815260200190815260200160002060030181905550826009600083815260200190815260200160002060040160006101000a81548160ff02191690831515021790555081600960008381526020019081526020016000206008018190555085876001600160a01b03167fd5dec9e768ba83c154ee9ecf7a0c145c8e7ee75e1cc4af2d271a1f9c93bb3946838888888860405180868152602001858152602001848152602001831515151581526020018281526020019550505050505060405180910390a361221c8185613703565b9695505050505050565b61222e6119d5565b61226d576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b60078054911515600160a01b0260ff60a01b19909216919091179055565b6000546001600160a01b031681565b600160009054906101000a90046001600160a01b03166001600160a01b031663e3bbb5656040518163ffffffff1660e01b815260040160206040518083038186803b1580156122e857600080fd5b505afa1580156122fc573d6000803e3d6000fd5b505050506040513d602081101561231257600080fd5b50516001600160a01b0316331461235a5760405162461bcd60e51b8152600401808060200182810382526043815260200180615a386043913960600191505060405180910390fd5b6000828152600960205260409020546001600160a01b038281169116148061239a5750612385610952565b6001600160a01b0316816001600160a01b0316145b6123d55760405162461bcd60e51b815260040180806020018281038252604381526020018061597f6043913960600191505060405180910390fd5b6000828152600960205260409020546001600160a01b03166124285760405162461bcd60e51b815260040180806020018281038252603c815260200180615883603c913960400191505060405180910390fd5b61243182612c41565b600082815260096020819052604080832080546001600160a01b031916815560018101849055600281018490556003810184905560048101805460ff1916905560058101849055600681018490556007810184905560088101849055918201839055600a8201839055600b8201839055600c8201839055600d8201839055600e8201839055600f8201839055601082018390556011820183905560128201839055601382018390556014909101829055516001600160a01b0383169184917fa6eb7cdc219e1518ced964e9a34e61d68a94e4f1569db3e84256ba981ba527539190a35050565b61251f6119d5565b61255e576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b600380546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f42c6bffb0e058cc1dfabd910037516fb01b87949d9a476876ff43179d62f4dc89181900360200190a150565b60006125bc6119d5565b6125fb576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b826001600160a01b031663a9059cbb6126126119c6565b846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561266257600080fd5b505af1158015612676573d6000803e3d6000fd5b505050506040513d602081101561268c57600080fd5b505190505b92915050565b61269f6119d5565b6126de576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b6126e7816137bc565b50565b60065481565b600081815260096020526040902080546001820154600283015460038401546004909401546126e7946001600160a01b03909416939060ff166133f6565b600081815260096020908152604091829020805460018083015460059093015490548551630f5fd3cf60e21b81526001600160a01b0393841660048201819052602482018690529651949592949190931692633d7f4f3c926044808301939192829003018186803b1580156127a257600080fd5b505afa1580156127b6573d6000803e3d6000fd5b505050506040513d60208110156127cc57600080fd5b5051811115612c3b57600154604080516377afd19160e11b81526001600160a01b038681166004830152602482018690529151600093929092169163ef5fa32291604480820192602092909190829003018186803b15801561282d57600080fd5b505afa158015612841573d6000803e3d6000fd5b505050506040513d602081101561285757600080fd5b50511115612a0a5760015460008581526009602081815260408084209092015482516301864ba360e41b81526001600160a01b038981166004830152602482018990529351939095169463be7e64b6948994899491928892631864ba3092604480840193829003018186803b1580156128cf57600080fd5b505afa1580156128e3573d6000803e3d6000fd5b505050506040513d60208110156128f957600080fd5b5051604080516001600160e01b031960e089901b1681526001600160a01b0390961660048701526024860194909452604485019290925260648401526084830152600060a4830181905260c483018190526305f5e10060e4840152610104830181905290516101248084019382900301818387803b15801561297a57600080fd5b505af115801561298e573d6000803e3d6000fd5b5050506000858152600960208181526040928390209182015460068301546007909301548451600181529283019190915281840192909252606081019190915290518492506001600160a01b038616917fe41babb55b71bb17aa9629797bcd2f80ff29c7c3fe5f8d20b8bf3b08d4e4f945919081900360800190a35b600154604080516301864ba360e41b81526001600160a01b0386811660048301526024820186905291516000939290921691631864ba3091604480820192602092909190829003018186803b158015612a6257600080fd5b505afa158015612a76573d6000803e3d6000fd5b505050506040513d6020811015612a8c57600080fd5b50511115612c3b576001546000858152600960208181526040928390209091015482516377afd19160e11b81526001600160a01b038881166004830152602482018890529351939094169363be7e64b6938893889392879263ef5fa32292604480840193919291829003018186803b158015612b0757600080fd5b505afa158015612b1b573d6000803e3d6000fd5b505050506040513d6020811015612b3157600080fd5b5051604080516001600160e01b031960e088901b1681526001600160a01b03909516600486015260248501939093526044840191909152606483015260006084830181905260a4830181905260c483018190526305f5e10060e4840152610104830181905290516101248084019382900301818387803b158015612bb457600080fd5b505af1158015612bc8573d6000803e3d6000fd5b5050506000858152600960208181526040808420928301546006840154600790940154825195865292850152838101929092526060830152518492506001600160a01b038616917fe41babb55b71bb17aa9629797bcd2f80ff29c7c3fe5f8d20b8bf3b08d4e4f945919081900360800190a35b50505050565b600081815260096020526040902060140154156126e75760008181526009602052604080822060148101805490849055600154600754925484516317d5759960e31b81526001600160a01b0394851660048201529084166024820152604481018390529351919492169263beabacc892606480830193919282900301818387803b158015612cce57600080fd5b505af1158015612ce2573d6000803e3d6000fd5b505050505050565b60008181526009602052604090206002015415612e735760018054600083815260096020908152604091829020805494015482516301864ba360e41b81526001600160a01b039586166004820152602481019190915291519390921692631864ba3092604480840193919291829003018186803b158015612d6a57600080fd5b505afa158015612d7e573d6000803e3d6000fd5b505050506040513d6020811015612d9457600080fd5b505160008281526009602052604090206002015411612dcb5760008181526009602052604090206002810154600b90910155612e73565b60018054600083815260096020908152604091829020805494015482516301864ba360e41b81526001600160a01b039586166004820152602481019190915291519390921692631864ba3092604480840193919291829003018186803b158015612e3457600080fd5b505afa158015612e48573d6000803e3d6000fd5b505050506040513d6020811015612e5e57600080fd5b50516000828152600960205260409020600b01555b60018054600083815260096020908152604091829020805494015482516301864ba360e41b81526001600160a01b039586166004820152602481019190915291519390921692631864ba3092604480840193919291829003018186803b158015612edc57600080fd5b505afa158015612ef0573d6000803e3d6000fd5b505050506040513d6020811015612f0657600080fd5b50516000828152600960205260409020600b0154148015612f37575060008181526009602052604090206003015415155b15612fa057600081815260096020526040812060068101546008820154600790920154612f8d93612f6f939142918491908490611389565b6000838152600960205260409020600301549063ffffffff61337216565b6000828152600960205260409020600a01555b6000818152600960205260409020600b015415612fc057612fc08161385c565b6000818152600960205260409020600a0154156126e7576126e781613c45565b600081815260096020526040902060020154156131695760018054600083815260096020908152604091829020805494015482516377afd19160e11b81526001600160a01b03958616600482015260248101919091529151939092169263ef5fa32292604480840193919291829003018186803b15801561306057600080fd5b505afa158015613074573d6000803e3d6000fd5b505050506040513d602081101561308a57600080fd5b5051600082815260096020526040902060020154116130c15760008181526009602052604090206002810154600a90910155613169565b60018054600083815260096020908152604091829020805494015482516377afd19160e11b81526001600160a01b03958616600482015260248101919091529151939092169263ef5fa32292604480840193919291829003018186803b15801561312a57600080fd5b505afa15801561313e573d6000803e3d6000fd5b505050506040513d602081101561315457600080fd5b50516000828152600960205260409020600a01555b60018054600083815260096020908152604091829020805494015482516377afd19160e11b81526001600160a01b03958616600482015260248101919091529151939092169263ef5fa32292604480840193919291829003018186803b1580156131d257600080fd5b505afa1580156131e6573d6000803e3d6000fd5b505050506040513d60208110156131fc57600080fd5b50516000828152600960205260409020600a015414801561322d575060008181526009602052604090206003015415155b156132785760008181526009602052604081206006810154600882015460079092015461326593612f6f93914291849190849061118b565b6000828152600960205260409020600b01555b6000818152600960205260409020600a0154156132985761329881614304565b6000818152600960205260409020600b0154156126e7576126e7816146a0565b600082820183811015613312576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b60008261332857506000612691565b8282028284828161333557fe5b04146133125760405162461bcd60e51b8152600401808060200182810382526021815260200180615a176021913960400191505060405180910390fd5b600061331283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614c3b565b600061331283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614cdd565b81156134b95760015460408051634a4cce9760e01b81526004810187905290516001600160a01b0390921691634a4cce9791602480820192602092909190829003018186803b15801561344857600080fd5b505afa15801561345c573d6000803e3d6000fd5b505050506040513d602081101561347257600080fd5b505115156001146134b45760405162461bcd60e51b8152600401808060200182810382526048815260200180615a7b6048913960600191505060405180910390fd5b6136fc565b60015460408051634a4cce9760e01b81526004810187905290516001600160a01b0390921691634a4cce9791602480820192602092909190829003018186803b15801561350557600080fd5b505afa158015613519573d6000803e3d6000fd5b505050506040513d602081101561352f57600080fd5b50516136fc576000613540856119e6565b1161357c5760405162461bcd60e51b815260040180806020018281038252605a8152602001806158bf605a913960600191505060405180910390fd5b801561363f57600154604080516301864ba360e41b81526001600160a01b0388811660048301526024820188905291519190921691631864ba30916044808301926020929190829003018186803b1580156135d657600080fd5b505afa1580156135ea573d6000803e3d6000fd5b505050506040513d602081101561360057600080fd5b505183146134b45760405162461bcd60e51b815260040180806020018281038252604a815260200180615790604a913960600191505060405180910390fd5b600154604080516377afd19160e11b81526001600160a01b038881166004830152602482018890529151919092169163ef5fa322916044808301926020929190829003018186803b15801561369357600080fd5b505afa1580156136a7573d6000803e3d6000fd5b505050506040513d60208110156136bd57600080fd5b505183146136fc5760405162461bcd60e51b815260040180806020018281038252604a815260200180615790604a913960600191505060405180910390fd5b5050505050565b600754600160a01b900460ff16801561371c5750600081115b156137b8576001546000838152600960205260408082205460075482516317d5759960e31b81526001600160a01b039283166004820152908216602482015260448101869052915193169263beabacc89260648084019391929182900301818387803b15801561378b57600080fd5b505af115801561379f573d6000803e3d6000fd5b5050506000838152600960205260409020601401829055505b5050565b6001600160a01b0381166138015760405162461bcd60e51b81526004018080602001828103825260288152602001806159576028913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60008181526009602090815260408083208054600180830154600b90930154905484516301864ba360e41b81526001600160a01b0393841660048201819052602482018690529551959794969495869586958695613914959094911692631864ba3092604480840193919291829003018186803b1580156138dc57600080fd5b505afa1580156138f0573d6000803e3d6000fd5b505050506040513d602081101561390657600080fd5b50519063ffffffff6133b416565b9050600061392188614d37565b600154604080516301864ba360e41b81526001600160a01b038b81166004830152602482018b90529151939450911691631864ba3091604480820192602092909190829003018186803b15801561397757600080fd5b505afa15801561398b573d6000803e3d6000fd5b505050506040513d60208110156139a157600080fd5b50516000898152600960205260409020600b015414156139cf5760009450600093506305f5e1009250613b5e565b6001546040805163e291f13560e01b81526001600160a01b038a81166004830152602482018a90529151919092169163e291f135916044808301926020929190829003018186803b158015613a2357600080fd5b505afa158015613a37573d6000803e3d6000fd5b505050506040513d6020811015613a4d57600080fd5b505160015460408051633bfbb2c160e21b81526001600160a01b038b81166004830152602482018b9052915193985091169163efeecb0491604480820192602092909190829003018186803b158015613aa557600080fd5b505afa158015613ab9573d6000803e3d6000fd5b505050506040513d6020811015613acf57600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038b81166004830152602482018b9052915193975091169163faddee1491604480820192602092909190829003018186803b158015613b2757600080fd5b505afa158015613b3b573d6000803e3d6000fd5b505050506040513d6020811015613b5157600080fd5b50519250613b5e886151f4565b6000888152600960209081526040808320600c810193909355600d8301849055600180548454919094015482516377afd19160e11b81526001600160a01b0392831660048201526024810191909152915193169263ef5fa32292604480840193919291829003018186803b158015613bd557600080fd5b505afa158015613be9573d6000803e3d6000fd5b505050506040513d6020811015613bff57600080fd5b50516000898152600960205260409020600e810191909155600f81018390556010810186905560118101859055601201839055613c3b886152fe565b5050505050505050565b6000818152600960209081526040808320805460019182015491548351633eb77b8560e21b81526001600160a01b0392831660048201819052602482018590529451949693959394859485949093169263faddee149260448082019391829003018186803b158015613cb657600080fd5b505afa158015613cca573d6000803e3d6000fd5b505050506040513d6020811015613ce057600080fd5b505190506305f5e100811015613cf757506305f5e1005b613d0b816305f5e10063ffffffff6133b416565b60008781526009602090815260409182902060060154600154835163e291f13560e01b81526001600160a01b038b81166004830152602482018b90529451959650613db59592946111f19492169263e291f13592604480840193919291829003018186803b158015613d7c57600080fd5b505afa158015613d90573d6000803e3d6000fd5b505050506040513d6020811015613da657600080fd5b5051849063ffffffff61331916565b60015460408051633eb77b8560e21b81526001600160a01b0389811660048301526024820189905291519394508493919092169163faddee14916044808301926020929190829003018186803b158015613e0e57600080fd5b505afa158015613e22573d6000803e3d6000fd5b505050506040513d6020811015613e3857600080fd5b50511115613e9e5760015460408051633eb77b8560e21b81526001600160a01b038881166004830152602482018890529151613e97938593169163faddee14916044808301926020929190829003018186803b1580156138dc57600080fd5b9050613ea2565b5060005b600154604080516377afd19160e11b81526001600160a01b038881166004830152602482018890529151600093613f40936305f5e100936111f193919092169163ef5fa322916044808301926020929190829003018186803b158015613f0757600080fd5b505afa158015613f1b573d6000803e3d6000fd5b505050506040513d6020811015613f3157600080fd5b5051859063ffffffff61331916565b60015460408051633eb77b8560e21b81526001600160a01b038a81166004830152602482018a90529151939450613fd6938593929092169163faddee1491604480820192602092909190829003018186803b158015613f9e57600080fd5b505afa158015613fb2573d6000803e3d6000fd5b505050506040513d6020811015613fc857600080fd5b50519063ffffffff61331916565b6000888152600960205260409020600a810154600890910154919450614005916112a49163ffffffff61331916565b6000888152600960205260409020600a015490935061403c9061402f90839063ffffffff6132b816565b849063ffffffff61337216565b600154604080516377afd19160e11b81526001600160a01b038a81166004830152602482018a9052915193965061411793919092169163ef5fa322916044808301926020929190829003018186803b15801561409757600080fd5b505afa1580156140ab573d6000803e3d6000fd5b505050506040513d60208110156140c157600080fd5b505160015460408051633bfbb2c160e21b81526001600160a01b038b81166004830152602482018b90529151919092169163efeecb04916044808301926020929190829003018186803b158015613f9e57600080fd5b6000888152600960205260409020600a810154600790910154919550614153916141469163ffffffff61331916565b859063ffffffff6132b816565b6000888152600960205260409020600a015490945061418a9061417d90839063ffffffff6132b816565b859063ffffffff61337216565b600088815260096020526040902060088101546007820154600a90920154929650614203926141db926305f5e100926111f19290916141cf919063ffffffff61331916565b9063ffffffff61331916565b60008981526009602052604090206006810154600a909101546114e89163ffffffff61331916565b6000888152600960205260408120600c810192909255600d820155600a015461423390829063ffffffff6132b816565b600088815260096020908152604091829020600e019290925560015481516301864ba360e41b81526001600160a01b038a81166004830152602482018a905292519290911692631864ba3092604480840193829003018186803b15801561429957600080fd5b505afa1580156142ad573d6000803e3d6000fd5b505050506040513d60208110156142c357600080fd5b50516000888152600960205260409020600f81019190915560068101546010820155601181018590556012018390556142fb876152fe565b50505050505050565b60008181526009602090815260408083208054600180830154600a90930154905484516377afd19160e11b81526001600160a01b039384166004820181905260248201869052955195979496949561437c9593949092169263ef5fa32292604480840193829003018186803b1580156138dc57600080fd5b9050600061438985614d37565b600154604080516377afd19160e11b81526001600160a01b03888116600483015260248201889052915193945060009384938493169163ef5fa322916044808301926020929190829003018186803b1580156143e457600080fd5b505afa1580156143f8573d6000803e3d6000fd5b505050506040513d602081101561440e57600080fd5b50516000898152600960205260409020600a0154141561443a5750600091508190506305f5e1006145c9565b6001546040805163e291f13560e01b81526001600160a01b038a81166004830152602482018a90529151919092169163e291f135916044808301926020929190829003018186803b15801561448e57600080fd5b505afa1580156144a2573d6000803e3d6000fd5b505050506040513d60208110156144b857600080fd5b505160015460408051633bfbb2c160e21b81526001600160a01b038b81166004830152602482018b9052915193965091169163efeecb0491604480820192602092909190829003018186803b15801561451057600080fd5b505afa158015614524573d6000803e3d6000fd5b505050506040513d602081101561453a57600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038b81166004830152602482018b9052915193955091169163faddee1491604480820192602092909190829003018186803b15801561459257600080fd5b505afa1580156145a6573d6000803e3d6000fd5b505050506040513d60208110156145bc57600080fd5b505190506145c9886151f4565b6000888152600960209081526040808320600c810193909355600d8301879055600e90920187905560015482516301864ba360e41b81526001600160a01b038b81166004830152602482018b905293519390911692631864ba3092604480840193919291829003018186803b15801561464157600080fd5b505afa158015614655573d6000803e3d6000fd5b505050506040513d602081101561466b57600080fd5b50516000898152600960205260409020600f8101919091556010810184905560118101839055601201819055613c3b886152fe565b6000818152600960209081526040808320805460019182015491548351633eb77b8560e21b81526001600160a01b0392831660048201819052602482018590529451949693959394859485949093169263faddee149260448082019391829003018186803b15801561471157600080fd5b505afa158015614725573d6000803e3d6000fd5b505050506040513d602081101561473b57600080fd5b505190506305f5e10081101561475257506305f5e1005b614766816305f5e10063ffffffff6132b816565b60008781526009602090815260409182902060060154600154835163e291f13560e01b81526001600160a01b038b81166004830152602482018b905294519596506147d79592946111f19492169263e291f13592604480840193919291829003018186803b158015613d7c57600080fd5b60015460408051633eb77b8560e21b81526001600160a01b0389811660048301526024820189905291519394508493919092169163faddee14916044808301926020929190829003018186803b15801561483057600080fd5b505afa158015614844573d6000803e3d6000fd5b505050506040513d602081101561485a57600080fd5b505110156148fb5760015460408051633eb77b8560e21b81526001600160a01b0388811660048301526024820188905291516148f493929092169163faddee1491604480820192602092909190829003018186803b1580156148bb57600080fd5b505afa1580156148cf573d6000803e3d6000fd5b505050506040513d60208110156148e557600080fd5b5051829063ffffffff6133b416565b90506148ff565b5060005b600154604080516301864ba360e41b81526001600160a01b038881166004830152602482018890529151600093614964936305f5e100936111f1939190921691631864ba30916044808301926020929190829003018186803b158015613f0757600080fd5b60015460408051633eb77b8560e21b81526001600160a01b038a81166004830152602482018a905291519394506149c2938593929092169163faddee1491604480820192602092909190829003018186803b158015613f9e57600080fd5b6000888152600960205260409020600b8101546008909101549194506149f1916112a49163ffffffff61331916565b6000888152600960205260409020600b0154909350614a1b9061402f90839063ffffffff6132b816565b600154604080516301864ba360e41b81526001600160a01b038a81166004830152602482018a90529151939650614a76939190921691631864ba30916044808301926020929190829003018186803b15801561409757600080fd5b6000888152600960205260409020600b810154600790910154919550614aa5916141469163ffffffff61331916565b6000888152600960205260409020600b0154909450614acf9061417d90839063ffffffff6132b816565b600088815260096020526040902060088101546007820154600b90920154929650614b3c92614b14926305f5e100926111f19290916141cf919063ffffffff61331916565b60008981526009602052604090206006810154600b909101546114e89163ffffffff61331916565b6000888152600960209081526040808320600c810194909455600d9093019190915560015482516377afd19160e11b81526001600160a01b038a81166004830152602482018a90529351939091169263ef5fa32292604480840193919291829003018186803b158015614bae57600080fd5b505afa158015614bc2573d6000803e3d6000fd5b505050506040513d6020811015614bd857600080fd5b50516000888152600960205260409020600e810191909155600b0154614c0590829063ffffffff6132b816565b6000888152600960205260409020600f81019190915560068101546010820155601181018590556012018390556142fb876152fe565b60008183614cc75760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614c8c578181015183820152602001614c74565b50505050905090810190601f168015614cb95780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581614cd357fe5b0495945050505050565b60008184841115614d2f5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614c8c578181015183820152602001614c74565b505050900390565b6000818152600960205260408120805460018201546004909201546001600160a01b039091169190839060ff16614fa857600085815260096020908152604091829020600a0154600154835163e291f13560e01b81526001600160a01b038881166004830152602482018890529451929850614fa1949091169263e291f13592604480840193829003018186803b158015614dd157600080fd5b505afa158015614de5573d6000803e3d6000fd5b505050506040513d6020811015614dfb57600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038881166004830152602482018890529151919092169163faddee14916044808301926020929190829003018186803b158015614e5157600080fd5b505afa158015614e65573d6000803e3d6000fd5b505050506040513d6020811015614e7b57600080fd5b505160015460408051630f5fd3cf60e21b81526001600160a01b0389811660048301526024820189905291519190921691633d7f4f3c916044808301926020929190829003018186803b158015614ed157600080fd5b505afa158015614ee5573d6000803e3d6000fd5b505050506040513d6020811015614efb57600080fd5b505160008981526009602090815260409182902060068101546007909101546001548451633eb77b8560e21b81526001600160a01b038d81166004830152602482018d9052955193959294929091169263faddee1492604480840193919291829003018186803b158015614f6e57600080fd5b505afa158015614f82573d6000803e3d6000fd5b505050506040513d6020811015614f9857600080fd5b50516001611389565b90506151e4565b600085815260096020908152604091829020600b0154600154835163e291f13560e01b81526001600160a01b0388811660048301526024820188905294519298506151e1949091169263e291f13592604480840193829003018186803b15801561501157600080fd5b505afa158015615025573d6000803e3d6000fd5b505050506040513d602081101561503b57600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038881166004830152602482018890529151919092169163faddee14916044808301926020929190829003018186803b15801561509157600080fd5b505afa1580156150a5573d6000803e3d6000fd5b505050506040513d60208110156150bb57600080fd5b505160015460408051630f5fd3cf60e21b81526001600160a01b0389811660048301526024820189905291519190921691633d7f4f3c916044808301926020929190829003018186803b15801561511157600080fd5b505afa158015615125573d6000803e3d6000fd5b505050506040513d602081101561513b57600080fd5b505160008981526009602090815260409182902060068101546007909101546001548451633eb77b8560e21b81526001600160a01b038d81166004830152602482018d9052955193959294929091169263faddee1492604480840193919291829003018186803b1580156151ae57600080fd5b505afa1580156151c2573d6000803e3d6000fd5b505050506040513d60208110156151d857600080fd5b5051600161118b565b90505b611922848263ffffffff61331916565b6000818152600960209081526040808320805460019182015491548351630f5fd3cf60e21b81526001600160a01b03928316600482018190526024820185905294519496939593949290911692633d7f4f3c92604480840193829003018186803b15801561526157600080fd5b505afa158015615275573d6000803e3d6000fd5b505050506040513d602081101561528b57600080fd5b50516000858152600960208181526040928390209091015482518881529182015280820183905290519192507f8c75318cfd6a0eae2329289b6827fd382e7324865986be09126ce67fc55bedc2919081900360600190a16000938452600960208190526040909420909301929092555050565b600081815260096020908152604091829020600c810154600d820154600154925485516370a0823160e01b81526001600160a01b039182166004820152955192956153a595929491909116926370a0823192602480840193919291829003018186803b15801561536d57600080fd5b505afa158015615381573d6000803e3d6000fd5b505050506040513d602081101561539757600080fd5b50519063ffffffff6132b816565b10156153e25760405162461bcd60e51b8152600401808060200182810382526027815260200180615b6d6027913960400191505060405180910390fd5b6153eb816112c1565b506000818152600960205260409020600c810154600d90910154111561544b576000818152600960205260409020600c810154600d909101546154339163ffffffff6133b416565b506000818152600960205260408120600c0155615487565b6000818152600960205260409020600d810154600c909101546154739163ffffffff6133b416565b506000818152600960205260408120600d01555b6000818152600960205260409020600d01541561551e576003546000828152600960205260408082208054600d9091015482516340c10f1960e01b81526001600160a01b039283166004820152602481019190915291519316926340c10f199260448084019391929182900301818387803b15801561550557600080fd5b505af1158015615519573d6000803e3d6000fd5b505050505b6000818152600960205260409020600c0154156155b5576001546000828152600960205260408082208054600c909101548251632770a7eb60e21b81526001600160a01b03928316600482015260248101919091529151931692639dc29fac9260448084019391929182900301818387803b15801561559c57600080fd5b505af11580156155b0573d6000803e3d6000fd5b505050505b60018054600083815260096020819052604080832080549581015492810154600e820154600f8301546010840154601185015460128601546013909601548751635f3f325b60e11b81526001600160a01b039c8d166004820152602481019990995260448901959095526064880193909352608487019190915260a486015260c485015260e484019190915261010483015251939092169263be7e64b69261012480820193929182900301818387803b15801561567157600080fd5b505af1158015615685573d6000803e3d6000fd5b5050506000828152600960208181526040928390208054600182015493820154600e830154600f8401546010850154601186015460128701546013880154600d890154600c909901548c516001600160a01b0390991689529988019a909a52868b01959095526060860193909352608085019190915260a084015260c083015260e082015261010081019390935261012083015261014082015290517f39cf7e0047b8651259e011d0b3ed8fc2c3dc2e49ed041f1651f06429698c1c949250908190036101600190a15056fe4d6f72706865725472616465456e67696e653a206c657665726167652065786365656473206d6178696d756d20616c6c6f776564206c657665726167652e4d6f72706865725472616465456e67696e653a204465616374697661746564206d61726b6574206f72646572206e6565647320616c6c2073686172657320746f20626520636c6f7365644d6f72706865725472616465456e67696e653a2043616e2774207061727469616c6c7920636c6f7365206120706f736974696f6e20616e64206f70656e20616e6f74686572206f6e6520696e206f70706f7369746520646972656374696f6e4d6f72706865725472616465456e67696e653a2072657175657374206578636565646564206d6178696d756d207065726d69747465642072657175657374732070657220626c6f636b2e4d6f72706865725472616465456e67696e653a20756e61626c6520746f2070726f636573732c206f7264657220646f6573206e6f742065786973742e4d6f72706865725472616465456e67696e653a2043616e277420636c6f7365206120706f736974696f6e2c206d61726b6574206e6f742061637469766520616e6420636c6f73696e67207072696365206e6f74206c6f636b65644d6f72706865725472616465456e67696e653a20756e61626c6520746f2070726f636573732c206f7264657220686173206265656e2064656c657465642e4f776e61626c653a207573652072656e6f756e6365206f776e65727368697020696e73746561642e4d6f72706865725472616465456e67696e653a206f6e6c792041646d696e6973747261746f72206f7220757365722063616e2063616e63656c20616e206f726465722e4d6f72706865725472616465456e67696e653a206d61726b6574207072696365206c6f776572207468656e206d61726b6574207370726561642e204f726465722063616e6e6f742062652070726f6365737365642e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774d6f72706865725472616465456e67696e653a2066756e6374696f6e2063616e206f6e6c792062652063616c6c6564206279204f7261636c6520436f6e74726163742e4d6f72706865725472616465456e67696e653a206d61726b657420756e6b6e6f776e206f722063757272656e746c79206e6f7420656e61626c656420666f722074726164696e672e4d6f72706865725472616465456e67696e653a206c6576657261676520746f6f20736d616c6c2e204c6576657261676520707265636973696f6e206973203165384d6f72706865725472616465456e67696e653a206d61726b657420707269636564206174207a65726f2e20427579206f726465722063616e6e6f742062652070726f6365737365642e4f776e61626c653a2063616c6c65722073686f756c64206265206f776e65722e4d6f72706865725472616465456e67696e653a20696e73756666696369656e742066756e64732ea265627a7a72315820cb9a00bd74f3aa4fa52897b6a4e7577ae149655caffe63aac6692578ab03023a64736f6c634300051000324f776e61626c653a207573652072656e6f756e6365206f776e65727368697020696e73746561642e8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e04f776e61626c653a2063616c6c65722073686f756c64206265206f776e65722e0000000000000000000000001f426c51f0ef7655a6f4c3eb58017d2f1c381bff00000000000000000000000051c5ce7c4926d5ca74f4824e11a062f1ef491762000000000000000000000000baf121d02e6948d3a089f99ddc522eb2a4a1b1fe0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d90c8a36fff52f1c8c05b54d4ce79610431ec0

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101cf5760003560e01c8063715018a611610104578063ac8f6f7f116100a2578063daf9502711610071578063daf9502714610575578063dc39d06d1461059b578063f2fde38b146105c7578063f40b7b32146105ed576101cf565b8063ac8f6f7f146104dc578063ac9eee2814610522578063b2bdfa7b14610541578063d61aed7a14610549576101cf565b806380104668116100de57806380104668146104895780638da5cb5b146104af5780638f32d59b146104b7578063a386fb56146104bf576101cf565b8063715018a61461042a5780637993a991146104325780637dffd04014610458576101cf565b80634702513c116101715780635778472a1161014b5780635778472a146103755780636950baa8146103d45780636b4f7065146103dc5780637023b78314610405576101cf565b80634702513c1461030d578063480ee2071461032a5780635662ecc71461036d576101cf565b806316f77a5b116101ad57806316f77a5b1461027357806316f8de89146102a857806323aab432146102c25780633754c565146102ca576101cf565b80630fa8f516146101d457806316194bac14610233578063169674071461024f575b600080fd5b610200600480360360408110156101ea57600080fd5b506001600160a01b0381351690602001356105f5565b604080519687526020870195909552858501939093526060850191909152608084015260a0830152519081900360c00190f35b61023b610942565b604080519115158252519081900360200190f35b610257610952565b604080516001600160a01b039092168252519081900360200190f35b610200600480360360a081101561028957600080fd5b50803590602081013590604081013590606081013590608001356109c8565b6102b0611176565b60408051918252519081900360200190f35b61025761117c565b6102b0600480360360e08110156102e057600080fd5b5080359060208101359060408101359060608101359060808101359060a08101359060c00135151561118b565b6102b06004803603602081101561032357600080fd5b50356112c1565b6102b0600480360360e081101561034057600080fd5b5080359060208101359060408101359060608101359060808101359060a08101359060c001351515611389565b6102b061140c565b6103926004803603602081101561038b57600080fd5b5035611412565b604080516001600160a01b0390981688526020880196909652868601949094526060860192909252608085015260a084015260c0830152519081900360e00190f35b610257611459565b6102b0600480360360608110156103f257600080fd5b5080359060208101359060400135611468565b6104286004803603604081101561041b57600080fd5b50803590602001356115a5565b005b610428611765565b6104286004803603602081101561044857600080fd5b50356001600160a01b03166117f6565b6102b06004803603608081101561046e57600080fd5b50803590602081013590604081013515159060600135611891565b6104286004803603602081101561049f57600080fd5b50356001600160a01b031661192b565b6102576119c6565b61023b6119d5565b6102b0600480360360208110156104d557600080fd5b50356119e6565b6102b0600480360360c08110156104f257600080fd5b506001600160a01b0381351690602081013590604081013590606081013590608081013515159060a00135611a75565b6104286004803603602081101561053857600080fd5b50351515612226565b61025761228b565b6104286004803603604081101561055f57600080fd5b50803590602001356001600160a01b031661229a565b6104286004803603602081101561058b57600080fd5b50356001600160a01b0316612517565b61023b600480360360408110156105b157600080fd5b506001600160a01b0381351690602001356125b2565b610428600480360360208110156105dd57600080fd5b50356001600160a01b0316612697565b6102b06126ea565b600154604080516377afd19160e11b81526001600160a01b03858116600483015260248201859052915160009384938493849384938493169163ef5fa322916044808301926020929190829003018186803b15801561065357600080fd5b505afa158015610667573d6000803e3d6000fd5b505050506040513d602081101561067d57600080fd5b5051600154604080516301864ba360e41b81526001600160a01b038c81166004830152602482018c905291519190921691631864ba30916044808301926020929190829003018186803b1580156106d357600080fd5b505afa1580156106e7573d6000803e3d6000fd5b505050506040513d60208110156106fd57600080fd5b50516001546040805163e291f13560e01b81526001600160a01b038d81166004830152602482018d90529151919092169163e291f135916044808301926020929190829003018186803b15801561075357600080fd5b505afa158015610767573d6000803e3d6000fd5b505050506040513d602081101561077d57600080fd5b505160015460408051633bfbb2c160e21b81526001600160a01b038e81166004830152602482018e90529151919092169163efeecb04916044808301926020929190829003018186803b1580156107d357600080fd5b505afa1580156107e7573d6000803e3d6000fd5b505050506040513d60208110156107fd57600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038f81166004830152602482018f90529151919092169163faddee14916044808301926020929190829003018186803b15801561085357600080fd5b505afa158015610867573d6000803e3d6000fd5b505050506040513d602081101561087d57600080fd5b8101908080519060200190929190505050600160009054906101000a90046001600160a01b03166001600160a01b031663652f17638e8e6040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b031681526020018281526020019250505060206040518083038186803b15801561090157600080fd5b505afa158015610915573d6000803e3d6000fd5b505050506040513d602081101561092b57600080fd5b5051949d939c50919a509850965090945092505050565b600754600160a01b900460ff1681565b60015460408051631696740760e01b815290516000926001600160a01b0316916316967407916004808301926020929190829003018186803b15801561099757600080fd5b505afa1580156109ab573d6000803e3d6000fd5b505050506040513d60208110156109c157600080fd5b5051905090565b600080600080600080600160009054906101000a90046001600160a01b03166001600160a01b031663e3bbb5656040518163ffffffff1660e01b815260040160206040518083038186803b158015610a1f57600080fd5b505afa158015610a33573d6000803e3d6000fd5b505050506040513d6020811015610a4957600080fd5b50516001600160a01b03163314610a915760405162461bcd60e51b8152600401808060200182810382526043815260200180615a386043913960600191505060405180910390fd5b60008b8152600960205260409020546001600160a01b0316610ae45760405162461bcd60e51b815260040180806020018281038252603e815260200180615919603e913960400191505060405180910390fd5b60008a11610b235760405162461bcd60e51b8152600401808060200182810382526049815260200180615b046049913960600191505060405180910390fd5b888a1015610b625760405162461bcd60e51b81526004018080602001828103825260558152602001806159c26055913960600191505060405180910390fd5b60008b815260096020818152604092839020600681018e9055600781018d90559182018a9055600582018b9055600180549201548351634a4cce9760e01b8152600481019190915292516001600160a01b0390921692634a4cce979260248083019392829003018186803b158015610bd957600080fd5b505afa158015610bed573d6000803e3d6000fd5b505050506040513d6020811015610c0357600080fd5b5051610c4057610c128b6126f0565b60008b815260096020526040902060010154610c2d906119e6565b60008c8152600960205260409020600601555b6001805460008d81526009602090815260409182902080549401548251630f5fd3cf60e21b81526001600160a01b039586166004820152602481019190915291519390921692633d7f4f3c92604480840193919291829003018186803b158015610ca957600080fd5b505afa158015610cbd573d6000803e3d6000fd5b505050506040513d6020811015610cd357600080fd5b5051881115610ce557610ce58b61272e565b610cee8b612c41565b60008b81526009602052604090206004015460ff1615610d1657610d118b612cea565b610d1f565b610d1f8b612fe0565b60008b815260096020818152604080842080546001820180546001600160a01b03198316845590879055600283018790556003830187905560048301805460ff1916905560058301879055600683018790556007830187905560088301879055948201869055600a8201869055600b8201869055600c8201869055600d8201869055600e8201869055600f82018690556010820186905560118201869055601282018690556013820186905560149091019490945580518f81529182018e90528181018d9052606082018c9052608082018b905260a082018a905260c0820189905260e08201889052610100820187905261012082018690526101408201859052516001600160a01b03909316927f696a3d28d7b4bcfc9cbfef719a03218d7a502cda20d01f9ef8086249e8165492918190036101600190a1600154604080516377afd19160e11b81526001600160a01b038581166004830152602482018590529151919092169163ef5fa322916044808301926020929190829003018186803b158015610eac57600080fd5b505afa158015610ec0573d6000803e3d6000fd5b505050506040513d6020811015610ed657600080fd5b5051600154604080516301864ba360e41b81526001600160a01b0386811660048301526024820186905291519190921691631864ba30916044808301926020929190829003018186803b158015610f2c57600080fd5b505afa158015610f40573d6000803e3d6000fd5b505050506040513d6020811015610f5657600080fd5b50516001546040805163e291f13560e01b81526001600160a01b038781166004830152602482018790529151919092169163e291f135916044808301926020929190829003018186803b158015610fac57600080fd5b505afa158015610fc0573d6000803e3d6000fd5b505050506040513d6020811015610fd657600080fd5b505160015460408051633bfbb2c160e21b81526001600160a01b038881166004830152602482018890529151919092169163efeecb04916044808301926020929190829003018186803b15801561102c57600080fd5b505afa158015611040573d6000803e3d6000fd5b505050506040513d602081101561105657600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038981166004830152602482018990529151919092169163faddee14916044808301926020929190829003018186803b1580156110ac57600080fd5b505afa1580156110c0573d6000803e3d6000fd5b505050506040513d60208110156110d657600080fd5b50516001546040805163652f176360e01b81526001600160a01b038a81166004830152602482018a90529151919092169163652f1763916044808301926020929190829003018186803b15801561112c57600080fd5b505afa158015611140573d6000803e3d6000fd5b505050506040513d602081101561115657600080fd5b5051949c50929a5090985096509450925050509550955095509550955095565b60045481565b6008546001600160a01b031681565b600087876305f5e1008110156111a257506305f5e1005b836111ad5750859050835b866111bb838360008c611891565b116111c957600092506112b4565b6111fd6305f5e1006111f16111e4828563ffffffff6132b816565b859063ffffffff61331916565b9063ffffffff61337216565b925061122761121a6305f5e1006111f18a8563ffffffff61331916565b849063ffffffff6133b416565b9250600184151514156112895761124f61121a6305f5e1006111f1898563ffffffff61331916565b9250600061125e83838b611468565b905083811161127e57611277848263ffffffff6133b416565b9350611283565b600093505b506112b4565b6112b16112a46305f5e1006111f1898963ffffffff61331916565b849063ffffffff6132b816565b92505b5050979650505050505050565b600081815260096020526040812060138101829055600e01541561132057600082815260096020819052604090912060108101546012820154919092015461130d929190600190611891565b6000838152600960205260409020601301555b6000828152600960205260409020600f01541561137357600082815260096020819052604082206010810154601282015491909201546113609390611891565b6000838152600960205260409020601301555b5060009081526009602052604090206013015490565b600087876305f5e1008110156113a057506305f5e1005b836113ab5750859050835b6113b8828260018b611891565b87116113c757600092506112b4565b6113e26305f5e1006111f16111e4848363ffffffff6133b416565b9250611227836114006305f5e1006111f18b8663ffffffff61331916565b9063ffffffff6133b416565b60055481565b60009081526009602052604090208054600182015460028301546003840154600685015460078601546008909601546001600160a01b039095169693959294919390929190565b6007546001600160a01b031681565b600654600090611480836103e863ffffffff61337216565b101561149e5760065461149b906103e863ffffffff61331916565b91505b6114b56111e4846305f5e10063ffffffff6133b416565b90506115016114f460016114e8620151806111f16114db886103e863ffffffff61337216565b429063ffffffff6133b416565b9063ffffffff6132b816565b829063ffffffff61331916565b905061159d6305f5e1006111f16305f5e1006111f1600260009054906101000a90046001600160a01b03166001600160a01b0316637c3a00fd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561156457600080fd5b505afa158015611578573d6000803e3d6000fd5b505050506040513d602081101561158e57600080fd5b5051869063ffffffff61331916565b949350505050565b600160009054906101000a90046001600160a01b03166001600160a01b031663e3bbb5656040518163ffffffff1660e01b815260040160206040518083038186803b1580156115f357600080fd5b505afa158015611607573d6000803e3d6000fd5b505050506040513d602081101561161d57600080fd5b50516001600160a01b031633146116655760405162461bcd60e51b8152600401808060200182810382526043815260200180615a386043913960600191505060405180910390fd5b6001546008546001600160a01b039182169163be7e64b6911684611691426103e863ffffffff61331916565b604080516001600160e01b031960e087901b1681526001600160a01b039094166004850152602484019290925260448301526000606483018190526084830181905260a4830186905260c4830181905260e48301819052610104830181905290516101248084019382900301818387803b15801561170e57600080fd5b505af1158015611722573d6000803e3d6000fd5b5050604080518581526020810185905281517f3cf30f15febef0d3f8e86318070db2c80d03fd14e8406d326aab41cb043f18399450908190039091019150a15050565b61176d6119d5565b6117ac576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6117fe6119d5565b61183d576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b600280546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4016bbc93bb2adf11f6d1b2509a1ab5f593cbe26e54875655329f9c80117f0849181900360200190a150565b6000600183151514156118ea576118c6846111f16118b9826305f5e10063ffffffff6133b416565b889063ffffffff61331916565b90506118e36118d6868685611468565b829063ffffffff6132b816565b905061159d565b611905846111f16118b9826305f5e10063ffffffff6132b816565b9050611922611915868685611468565b829063ffffffff6133b416565b95945050505050565b6119336119d5565b611972576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f978c711532bae8c58f353b0f3c7f3a0dfe600d9ae9a81818f2ad2919b88e19909181900360200190a150565b6000546001600160a01b031690565b6000546001600160a01b0316331490565b600154600854604080516307d47a8b60e11b81526001600160a01b03928316600482015260248101859052905160009384931691630fa8f5169160448083019260c0929190829003018186803b158015611a3f57600080fd5b505afa158015611a53573d6000803e3d6000fd5b505050506040513d60c0811015611a6957600080fd5b50604001519392505050565b6001546040805163e3bbb56560e01b815290516000926001600160a01b03169163e3bbb565916004808301926020929190829003018186803b158015611aba57600080fd5b505afa158015611ace573d6000803e3d6000fd5b505050506040513d6020811015611ae457600080fd5b50516001600160a01b03163314611b2c5760405162461bcd60e51b8152600401808060200182810382526043815260200180615a386043913960600191505060405180910390fd5b6305f5e100821015611b6f5760405162461bcd60e51b8152600401808060200182810382526041815260200180615ac36041913960600191505060405180910390fd5b600160009054906101000a90046001600160a01b03166001600160a01b0316637c995e916040518163ffffffff1660e01b815260040160206040518083038186803b158015611bbd57600080fd5b505afa158015611bd1573d6000803e3d6000fd5b505050506040513d6020811015611be757600080fd5b5051821115611c275760405162461bcd60e51b815260040180806020018281038252603e815260200180615752603e913960400191505060405180910390fd5b611c3487878787876133f6565b600160009054906101000a90046001600160a01b03166001600160a01b031663755ca87a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c8257600080fd5b505afa158015611c96573d6000803e3d6000fd5b505050506040513d6020811015611cac57600080fd5b505160015460408051631722e4cd60e21b81526001600160a01b038b8116600483015291519190921691635c8b9334916024808301926020929190829003018186803b158015611cfb57600080fd5b505afa158015611d0f573d6000803e3d6000fd5b505050506040513d6020811015611d2557600080fd5b5051111580611dad5750600154604080516330826beb60e21b81526001600160a01b038a8116600483015291514393929092169163c209afac91602480820192602092909190829003018186803b158015611d7f57600080fd5b505afa158015611d93573d6000803e3d6000fd5b505050506040513d6020811015611da957600080fd5b5051105b611de85760405162461bcd60e51b815260040180806020018281038252604a815260200180615839604a913960600191505060405180910390fd5b8315611f73578215611eb657600154604080516301864ba360e41b81526001600160a01b038a81166004830152602482018a905291519190921691631864ba30916044808301926020929190829003018186803b158015611e4857600080fd5b505afa158015611e5c573d6000803e3d6000fd5b505050506040513d6020811015611e7257600080fd5b50518514611eb15760405162461bcd60e51b815260040180806020018281038252605f8152602001806157da605f913960600191505060405180910390fd5b611f73565b600154604080516377afd19160e11b81526001600160a01b038a81166004830152602482018a90529151919092169163ef5fa322916044808301926020929190829003018186803b158015611f0a57600080fd5b505afa158015611f1e573d6000803e3d6000fd5b505050506040513d6020811015611f3457600080fd5b50518514611f735760405162461bcd60e51b815260040180806020018281038252605f8152602001806157da605f913960600191505060405180910390fd5b600154604080516303d4880760e11b81526001600160a01b038a81166004830152915191909216916307a9100e91602480830192600092919082900301818387803b158015611fc157600080fd5b505af1158015611fd5573d6000803e3d6000fd5b505060015460408051635e61f1a160e11b81526001600160a01b038c81166004830152915191909216935063bcc3e3429250602480830192600092919082900301818387803b15801561202757600080fd5b505af115801561203b573d6000803e3d6000fd5b505050506004600081548092919060010191905055508643878787878760045460405160200180896001600160a01b03166001600160a01b031660601b8152601401888152602001878152602001868152602001858152602001841515151560f81b81526001018381526020018281526020019850505050505050505060405160208183030381529060405280519060200120905080600581905550866009600083815260200190815260200160002060000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550856009600083815260200190815260200160002060010181905550846009600083815260200190815260200160002060020181905550836009600083815260200190815260200160002060030181905550826009600083815260200190815260200160002060040160006101000a81548160ff02191690831515021790555081600960008381526020019081526020016000206008018190555085876001600160a01b03167fd5dec9e768ba83c154ee9ecf7a0c145c8e7ee75e1cc4af2d271a1f9c93bb3946838888888860405180868152602001858152602001848152602001831515151581526020018281526020019550505050505060405180910390a361221c8185613703565b9695505050505050565b61222e6119d5565b61226d576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b60078054911515600160a01b0260ff60a01b19909216919091179055565b6000546001600160a01b031681565b600160009054906101000a90046001600160a01b03166001600160a01b031663e3bbb5656040518163ffffffff1660e01b815260040160206040518083038186803b1580156122e857600080fd5b505afa1580156122fc573d6000803e3d6000fd5b505050506040513d602081101561231257600080fd5b50516001600160a01b0316331461235a5760405162461bcd60e51b8152600401808060200182810382526043815260200180615a386043913960600191505060405180910390fd5b6000828152600960205260409020546001600160a01b038281169116148061239a5750612385610952565b6001600160a01b0316816001600160a01b0316145b6123d55760405162461bcd60e51b815260040180806020018281038252604381526020018061597f6043913960600191505060405180910390fd5b6000828152600960205260409020546001600160a01b03166124285760405162461bcd60e51b815260040180806020018281038252603c815260200180615883603c913960400191505060405180910390fd5b61243182612c41565b600082815260096020819052604080832080546001600160a01b031916815560018101849055600281018490556003810184905560048101805460ff1916905560058101849055600681018490556007810184905560088101849055918201839055600a8201839055600b8201839055600c8201839055600d8201839055600e8201839055600f8201839055601082018390556011820183905560128201839055601382018390556014909101829055516001600160a01b0383169184917fa6eb7cdc219e1518ced964e9a34e61d68a94e4f1569db3e84256ba981ba527539190a35050565b61251f6119d5565b61255e576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b600380546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f42c6bffb0e058cc1dfabd910037516fb01b87949d9a476876ff43179d62f4dc89181900360200190a150565b60006125bc6119d5565b6125fb576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b826001600160a01b031663a9059cbb6126126119c6565b846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561266257600080fd5b505af1158015612676573d6000803e3d6000fd5b505050506040513d602081101561268c57600080fd5b505190505b92915050565b61269f6119d5565b6126de576040805162461bcd60e51b81526020600482018190526024820152600080516020615b4d833981519152604482015290519081900360640190fd5b6126e7816137bc565b50565b60065481565b600081815260096020526040902080546001820154600283015460038401546004909401546126e7946001600160a01b03909416939060ff166133f6565b600081815260096020908152604091829020805460018083015460059093015490548551630f5fd3cf60e21b81526001600160a01b0393841660048201819052602482018690529651949592949190931692633d7f4f3c926044808301939192829003018186803b1580156127a257600080fd5b505afa1580156127b6573d6000803e3d6000fd5b505050506040513d60208110156127cc57600080fd5b5051811115612c3b57600154604080516377afd19160e11b81526001600160a01b038681166004830152602482018690529151600093929092169163ef5fa32291604480820192602092909190829003018186803b15801561282d57600080fd5b505afa158015612841573d6000803e3d6000fd5b505050506040513d602081101561285757600080fd5b50511115612a0a5760015460008581526009602081815260408084209092015482516301864ba360e41b81526001600160a01b038981166004830152602482018990529351939095169463be7e64b6948994899491928892631864ba3092604480840193829003018186803b1580156128cf57600080fd5b505afa1580156128e3573d6000803e3d6000fd5b505050506040513d60208110156128f957600080fd5b5051604080516001600160e01b031960e089901b1681526001600160a01b0390961660048701526024860194909452604485019290925260648401526084830152600060a4830181905260c483018190526305f5e10060e4840152610104830181905290516101248084019382900301818387803b15801561297a57600080fd5b505af115801561298e573d6000803e3d6000fd5b5050506000858152600960208181526040928390209182015460068301546007909301548451600181529283019190915281840192909252606081019190915290518492506001600160a01b038616917fe41babb55b71bb17aa9629797bcd2f80ff29c7c3fe5f8d20b8bf3b08d4e4f945919081900360800190a35b600154604080516301864ba360e41b81526001600160a01b0386811660048301526024820186905291516000939290921691631864ba3091604480820192602092909190829003018186803b158015612a6257600080fd5b505afa158015612a76573d6000803e3d6000fd5b505050506040513d6020811015612a8c57600080fd5b50511115612c3b576001546000858152600960208181526040928390209091015482516377afd19160e11b81526001600160a01b038881166004830152602482018890529351939094169363be7e64b6938893889392879263ef5fa32292604480840193919291829003018186803b158015612b0757600080fd5b505afa158015612b1b573d6000803e3d6000fd5b505050506040513d6020811015612b3157600080fd5b5051604080516001600160e01b031960e088901b1681526001600160a01b03909516600486015260248501939093526044840191909152606483015260006084830181905260a4830181905260c483018190526305f5e10060e4840152610104830181905290516101248084019382900301818387803b158015612bb457600080fd5b505af1158015612bc8573d6000803e3d6000fd5b5050506000858152600960208181526040808420928301546006840154600790940154825195865292850152838101929092526060830152518492506001600160a01b038616917fe41babb55b71bb17aa9629797bcd2f80ff29c7c3fe5f8d20b8bf3b08d4e4f945919081900360800190a35b50505050565b600081815260096020526040902060140154156126e75760008181526009602052604080822060148101805490849055600154600754925484516317d5759960e31b81526001600160a01b0394851660048201529084166024820152604481018390529351919492169263beabacc892606480830193919282900301818387803b158015612cce57600080fd5b505af1158015612ce2573d6000803e3d6000fd5b505050505050565b60008181526009602052604090206002015415612e735760018054600083815260096020908152604091829020805494015482516301864ba360e41b81526001600160a01b039586166004820152602481019190915291519390921692631864ba3092604480840193919291829003018186803b158015612d6a57600080fd5b505afa158015612d7e573d6000803e3d6000fd5b505050506040513d6020811015612d9457600080fd5b505160008281526009602052604090206002015411612dcb5760008181526009602052604090206002810154600b90910155612e73565b60018054600083815260096020908152604091829020805494015482516301864ba360e41b81526001600160a01b039586166004820152602481019190915291519390921692631864ba3092604480840193919291829003018186803b158015612e3457600080fd5b505afa158015612e48573d6000803e3d6000fd5b505050506040513d6020811015612e5e57600080fd5b50516000828152600960205260409020600b01555b60018054600083815260096020908152604091829020805494015482516301864ba360e41b81526001600160a01b039586166004820152602481019190915291519390921692631864ba3092604480840193919291829003018186803b158015612edc57600080fd5b505afa158015612ef0573d6000803e3d6000fd5b505050506040513d6020811015612f0657600080fd5b50516000828152600960205260409020600b0154148015612f37575060008181526009602052604090206003015415155b15612fa057600081815260096020526040812060068101546008820154600790920154612f8d93612f6f939142918491908490611389565b6000838152600960205260409020600301549063ffffffff61337216565b6000828152600960205260409020600a01555b6000818152600960205260409020600b015415612fc057612fc08161385c565b6000818152600960205260409020600a0154156126e7576126e781613c45565b600081815260096020526040902060020154156131695760018054600083815260096020908152604091829020805494015482516377afd19160e11b81526001600160a01b03958616600482015260248101919091529151939092169263ef5fa32292604480840193919291829003018186803b15801561306057600080fd5b505afa158015613074573d6000803e3d6000fd5b505050506040513d602081101561308a57600080fd5b5051600082815260096020526040902060020154116130c15760008181526009602052604090206002810154600a90910155613169565b60018054600083815260096020908152604091829020805494015482516377afd19160e11b81526001600160a01b03958616600482015260248101919091529151939092169263ef5fa32292604480840193919291829003018186803b15801561312a57600080fd5b505afa15801561313e573d6000803e3d6000fd5b505050506040513d602081101561315457600080fd5b50516000828152600960205260409020600a01555b60018054600083815260096020908152604091829020805494015482516377afd19160e11b81526001600160a01b03958616600482015260248101919091529151939092169263ef5fa32292604480840193919291829003018186803b1580156131d257600080fd5b505afa1580156131e6573d6000803e3d6000fd5b505050506040513d60208110156131fc57600080fd5b50516000828152600960205260409020600a015414801561322d575060008181526009602052604090206003015415155b156132785760008181526009602052604081206006810154600882015460079092015461326593612f6f93914291849190849061118b565b6000828152600960205260409020600b01555b6000818152600960205260409020600a0154156132985761329881614304565b6000818152600960205260409020600b0154156126e7576126e7816146a0565b600082820183811015613312576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b60008261332857506000612691565b8282028284828161333557fe5b04146133125760405162461bcd60e51b8152600401808060200182810382526021815260200180615a176021913960400191505060405180910390fd5b600061331283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614c3b565b600061331283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614cdd565b81156134b95760015460408051634a4cce9760e01b81526004810187905290516001600160a01b0390921691634a4cce9791602480820192602092909190829003018186803b15801561344857600080fd5b505afa15801561345c573d6000803e3d6000fd5b505050506040513d602081101561347257600080fd5b505115156001146134b45760405162461bcd60e51b8152600401808060200182810382526048815260200180615a7b6048913960600191505060405180910390fd5b6136fc565b60015460408051634a4cce9760e01b81526004810187905290516001600160a01b0390921691634a4cce9791602480820192602092909190829003018186803b15801561350557600080fd5b505afa158015613519573d6000803e3d6000fd5b505050506040513d602081101561352f57600080fd5b50516136fc576000613540856119e6565b1161357c5760405162461bcd60e51b815260040180806020018281038252605a8152602001806158bf605a913960600191505060405180910390fd5b801561363f57600154604080516301864ba360e41b81526001600160a01b0388811660048301526024820188905291519190921691631864ba30916044808301926020929190829003018186803b1580156135d657600080fd5b505afa1580156135ea573d6000803e3d6000fd5b505050506040513d602081101561360057600080fd5b505183146134b45760405162461bcd60e51b815260040180806020018281038252604a815260200180615790604a913960600191505060405180910390fd5b600154604080516377afd19160e11b81526001600160a01b038881166004830152602482018890529151919092169163ef5fa322916044808301926020929190829003018186803b15801561369357600080fd5b505afa1580156136a7573d6000803e3d6000fd5b505050506040513d60208110156136bd57600080fd5b505183146136fc5760405162461bcd60e51b815260040180806020018281038252604a815260200180615790604a913960600191505060405180910390fd5b5050505050565b600754600160a01b900460ff16801561371c5750600081115b156137b8576001546000838152600960205260408082205460075482516317d5759960e31b81526001600160a01b039283166004820152908216602482015260448101869052915193169263beabacc89260648084019391929182900301818387803b15801561378b57600080fd5b505af115801561379f573d6000803e3d6000fd5b5050506000838152600960205260409020601401829055505b5050565b6001600160a01b0381166138015760405162461bcd60e51b81526004018080602001828103825260288152602001806159576028913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60008181526009602090815260408083208054600180830154600b90930154905484516301864ba360e41b81526001600160a01b0393841660048201819052602482018690529551959794969495869586958695613914959094911692631864ba3092604480840193919291829003018186803b1580156138dc57600080fd5b505afa1580156138f0573d6000803e3d6000fd5b505050506040513d602081101561390657600080fd5b50519063ffffffff6133b416565b9050600061392188614d37565b600154604080516301864ba360e41b81526001600160a01b038b81166004830152602482018b90529151939450911691631864ba3091604480820192602092909190829003018186803b15801561397757600080fd5b505afa15801561398b573d6000803e3d6000fd5b505050506040513d60208110156139a157600080fd5b50516000898152600960205260409020600b015414156139cf5760009450600093506305f5e1009250613b5e565b6001546040805163e291f13560e01b81526001600160a01b038a81166004830152602482018a90529151919092169163e291f135916044808301926020929190829003018186803b158015613a2357600080fd5b505afa158015613a37573d6000803e3d6000fd5b505050506040513d6020811015613a4d57600080fd5b505160015460408051633bfbb2c160e21b81526001600160a01b038b81166004830152602482018b9052915193985091169163efeecb0491604480820192602092909190829003018186803b158015613aa557600080fd5b505afa158015613ab9573d6000803e3d6000fd5b505050506040513d6020811015613acf57600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038b81166004830152602482018b9052915193975091169163faddee1491604480820192602092909190829003018186803b158015613b2757600080fd5b505afa158015613b3b573d6000803e3d6000fd5b505050506040513d6020811015613b5157600080fd5b50519250613b5e886151f4565b6000888152600960209081526040808320600c810193909355600d8301849055600180548454919094015482516377afd19160e11b81526001600160a01b0392831660048201526024810191909152915193169263ef5fa32292604480840193919291829003018186803b158015613bd557600080fd5b505afa158015613be9573d6000803e3d6000fd5b505050506040513d6020811015613bff57600080fd5b50516000898152600960205260409020600e810191909155600f81018390556010810186905560118101859055601201839055613c3b886152fe565b5050505050505050565b6000818152600960209081526040808320805460019182015491548351633eb77b8560e21b81526001600160a01b0392831660048201819052602482018590529451949693959394859485949093169263faddee149260448082019391829003018186803b158015613cb657600080fd5b505afa158015613cca573d6000803e3d6000fd5b505050506040513d6020811015613ce057600080fd5b505190506305f5e100811015613cf757506305f5e1005b613d0b816305f5e10063ffffffff6133b416565b60008781526009602090815260409182902060060154600154835163e291f13560e01b81526001600160a01b038b81166004830152602482018b90529451959650613db59592946111f19492169263e291f13592604480840193919291829003018186803b158015613d7c57600080fd5b505afa158015613d90573d6000803e3d6000fd5b505050506040513d6020811015613da657600080fd5b5051849063ffffffff61331916565b60015460408051633eb77b8560e21b81526001600160a01b0389811660048301526024820189905291519394508493919092169163faddee14916044808301926020929190829003018186803b158015613e0e57600080fd5b505afa158015613e22573d6000803e3d6000fd5b505050506040513d6020811015613e3857600080fd5b50511115613e9e5760015460408051633eb77b8560e21b81526001600160a01b038881166004830152602482018890529151613e97938593169163faddee14916044808301926020929190829003018186803b1580156138dc57600080fd5b9050613ea2565b5060005b600154604080516377afd19160e11b81526001600160a01b038881166004830152602482018890529151600093613f40936305f5e100936111f193919092169163ef5fa322916044808301926020929190829003018186803b158015613f0757600080fd5b505afa158015613f1b573d6000803e3d6000fd5b505050506040513d6020811015613f3157600080fd5b5051859063ffffffff61331916565b60015460408051633eb77b8560e21b81526001600160a01b038a81166004830152602482018a90529151939450613fd6938593929092169163faddee1491604480820192602092909190829003018186803b158015613f9e57600080fd5b505afa158015613fb2573d6000803e3d6000fd5b505050506040513d6020811015613fc857600080fd5b50519063ffffffff61331916565b6000888152600960205260409020600a810154600890910154919450614005916112a49163ffffffff61331916565b6000888152600960205260409020600a015490935061403c9061402f90839063ffffffff6132b816565b849063ffffffff61337216565b600154604080516377afd19160e11b81526001600160a01b038a81166004830152602482018a9052915193965061411793919092169163ef5fa322916044808301926020929190829003018186803b15801561409757600080fd5b505afa1580156140ab573d6000803e3d6000fd5b505050506040513d60208110156140c157600080fd5b505160015460408051633bfbb2c160e21b81526001600160a01b038b81166004830152602482018b90529151919092169163efeecb04916044808301926020929190829003018186803b158015613f9e57600080fd5b6000888152600960205260409020600a810154600790910154919550614153916141469163ffffffff61331916565b859063ffffffff6132b816565b6000888152600960205260409020600a015490945061418a9061417d90839063ffffffff6132b816565b859063ffffffff61337216565b600088815260096020526040902060088101546007820154600a90920154929650614203926141db926305f5e100926111f19290916141cf919063ffffffff61331916565b9063ffffffff61331916565b60008981526009602052604090206006810154600a909101546114e89163ffffffff61331916565b6000888152600960205260408120600c810192909255600d820155600a015461423390829063ffffffff6132b816565b600088815260096020908152604091829020600e019290925560015481516301864ba360e41b81526001600160a01b038a81166004830152602482018a905292519290911692631864ba3092604480840193829003018186803b15801561429957600080fd5b505afa1580156142ad573d6000803e3d6000fd5b505050506040513d60208110156142c357600080fd5b50516000888152600960205260409020600f81019190915560068101546010820155601181018590556012018390556142fb876152fe565b50505050505050565b60008181526009602090815260408083208054600180830154600a90930154905484516377afd19160e11b81526001600160a01b039384166004820181905260248201869052955195979496949561437c9593949092169263ef5fa32292604480840193829003018186803b1580156138dc57600080fd5b9050600061438985614d37565b600154604080516377afd19160e11b81526001600160a01b03888116600483015260248201889052915193945060009384938493169163ef5fa322916044808301926020929190829003018186803b1580156143e457600080fd5b505afa1580156143f8573d6000803e3d6000fd5b505050506040513d602081101561440e57600080fd5b50516000898152600960205260409020600a0154141561443a5750600091508190506305f5e1006145c9565b6001546040805163e291f13560e01b81526001600160a01b038a81166004830152602482018a90529151919092169163e291f135916044808301926020929190829003018186803b15801561448e57600080fd5b505afa1580156144a2573d6000803e3d6000fd5b505050506040513d60208110156144b857600080fd5b505160015460408051633bfbb2c160e21b81526001600160a01b038b81166004830152602482018b9052915193965091169163efeecb0491604480820192602092909190829003018186803b15801561451057600080fd5b505afa158015614524573d6000803e3d6000fd5b505050506040513d602081101561453a57600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038b81166004830152602482018b9052915193955091169163faddee1491604480820192602092909190829003018186803b15801561459257600080fd5b505afa1580156145a6573d6000803e3d6000fd5b505050506040513d60208110156145bc57600080fd5b505190506145c9886151f4565b6000888152600960209081526040808320600c810193909355600d8301879055600e90920187905560015482516301864ba360e41b81526001600160a01b038b81166004830152602482018b905293519390911692631864ba3092604480840193919291829003018186803b15801561464157600080fd5b505afa158015614655573d6000803e3d6000fd5b505050506040513d602081101561466b57600080fd5b50516000898152600960205260409020600f8101919091556010810184905560118101839055601201819055613c3b886152fe565b6000818152600960209081526040808320805460019182015491548351633eb77b8560e21b81526001600160a01b0392831660048201819052602482018590529451949693959394859485949093169263faddee149260448082019391829003018186803b15801561471157600080fd5b505afa158015614725573d6000803e3d6000fd5b505050506040513d602081101561473b57600080fd5b505190506305f5e10081101561475257506305f5e1005b614766816305f5e10063ffffffff6132b816565b60008781526009602090815260409182902060060154600154835163e291f13560e01b81526001600160a01b038b81166004830152602482018b905294519596506147d79592946111f19492169263e291f13592604480840193919291829003018186803b158015613d7c57600080fd5b60015460408051633eb77b8560e21b81526001600160a01b0389811660048301526024820189905291519394508493919092169163faddee14916044808301926020929190829003018186803b15801561483057600080fd5b505afa158015614844573d6000803e3d6000fd5b505050506040513d602081101561485a57600080fd5b505110156148fb5760015460408051633eb77b8560e21b81526001600160a01b0388811660048301526024820188905291516148f493929092169163faddee1491604480820192602092909190829003018186803b1580156148bb57600080fd5b505afa1580156148cf573d6000803e3d6000fd5b505050506040513d60208110156148e557600080fd5b5051829063ffffffff6133b416565b90506148ff565b5060005b600154604080516301864ba360e41b81526001600160a01b038881166004830152602482018890529151600093614964936305f5e100936111f1939190921691631864ba30916044808301926020929190829003018186803b158015613f0757600080fd5b60015460408051633eb77b8560e21b81526001600160a01b038a81166004830152602482018a905291519394506149c2938593929092169163faddee1491604480820192602092909190829003018186803b158015613f9e57600080fd5b6000888152600960205260409020600b8101546008909101549194506149f1916112a49163ffffffff61331916565b6000888152600960205260409020600b0154909350614a1b9061402f90839063ffffffff6132b816565b600154604080516301864ba360e41b81526001600160a01b038a81166004830152602482018a90529151939650614a76939190921691631864ba30916044808301926020929190829003018186803b15801561409757600080fd5b6000888152600960205260409020600b810154600790910154919550614aa5916141469163ffffffff61331916565b6000888152600960205260409020600b0154909450614acf9061417d90839063ffffffff6132b816565b600088815260096020526040902060088101546007820154600b90920154929650614b3c92614b14926305f5e100926111f19290916141cf919063ffffffff61331916565b60008981526009602052604090206006810154600b909101546114e89163ffffffff61331916565b6000888152600960209081526040808320600c810194909455600d9093019190915560015482516377afd19160e11b81526001600160a01b038a81166004830152602482018a90529351939091169263ef5fa32292604480840193919291829003018186803b158015614bae57600080fd5b505afa158015614bc2573d6000803e3d6000fd5b505050506040513d6020811015614bd857600080fd5b50516000888152600960205260409020600e810191909155600b0154614c0590829063ffffffff6132b816565b6000888152600960205260409020600f81019190915560068101546010820155601181018590556012018390556142fb876152fe565b60008183614cc75760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614c8c578181015183820152602001614c74565b50505050905090810190601f168015614cb95780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581614cd357fe5b0495945050505050565b60008184841115614d2f5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614c8c578181015183820152602001614c74565b505050900390565b6000818152600960205260408120805460018201546004909201546001600160a01b039091169190839060ff16614fa857600085815260096020908152604091829020600a0154600154835163e291f13560e01b81526001600160a01b038881166004830152602482018890529451929850614fa1949091169263e291f13592604480840193829003018186803b158015614dd157600080fd5b505afa158015614de5573d6000803e3d6000fd5b505050506040513d6020811015614dfb57600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038881166004830152602482018890529151919092169163faddee14916044808301926020929190829003018186803b158015614e5157600080fd5b505afa158015614e65573d6000803e3d6000fd5b505050506040513d6020811015614e7b57600080fd5b505160015460408051630f5fd3cf60e21b81526001600160a01b0389811660048301526024820189905291519190921691633d7f4f3c916044808301926020929190829003018186803b158015614ed157600080fd5b505afa158015614ee5573d6000803e3d6000fd5b505050506040513d6020811015614efb57600080fd5b505160008981526009602090815260409182902060068101546007909101546001548451633eb77b8560e21b81526001600160a01b038d81166004830152602482018d9052955193959294929091169263faddee1492604480840193919291829003018186803b158015614f6e57600080fd5b505afa158015614f82573d6000803e3d6000fd5b505050506040513d6020811015614f9857600080fd5b50516001611389565b90506151e4565b600085815260096020908152604091829020600b0154600154835163e291f13560e01b81526001600160a01b0388811660048301526024820188905294519298506151e1949091169263e291f13592604480840193829003018186803b15801561501157600080fd5b505afa158015615025573d6000803e3d6000fd5b505050506040513d602081101561503b57600080fd5b505160015460408051633eb77b8560e21b81526001600160a01b038881166004830152602482018890529151919092169163faddee14916044808301926020929190829003018186803b15801561509157600080fd5b505afa1580156150a5573d6000803e3d6000fd5b505050506040513d60208110156150bb57600080fd5b505160015460408051630f5fd3cf60e21b81526001600160a01b0389811660048301526024820189905291519190921691633d7f4f3c916044808301926020929190829003018186803b15801561511157600080fd5b505afa158015615125573d6000803e3d6000fd5b505050506040513d602081101561513b57600080fd5b505160008981526009602090815260409182902060068101546007909101546001548451633eb77b8560e21b81526001600160a01b038d81166004830152602482018d9052955193959294929091169263faddee1492604480840193919291829003018186803b1580156151ae57600080fd5b505afa1580156151c2573d6000803e3d6000fd5b505050506040513d60208110156151d857600080fd5b5051600161118b565b90505b611922848263ffffffff61331916565b6000818152600960209081526040808320805460019182015491548351630f5fd3cf60e21b81526001600160a01b03928316600482018190526024820185905294519496939593949290911692633d7f4f3c92604480840193829003018186803b15801561526157600080fd5b505afa158015615275573d6000803e3d6000fd5b505050506040513d602081101561528b57600080fd5b50516000858152600960208181526040928390209091015482518881529182015280820183905290519192507f8c75318cfd6a0eae2329289b6827fd382e7324865986be09126ce67fc55bedc2919081900360600190a16000938452600960208190526040909420909301929092555050565b600081815260096020908152604091829020600c810154600d820154600154925485516370a0823160e01b81526001600160a01b039182166004820152955192956153a595929491909116926370a0823192602480840193919291829003018186803b15801561536d57600080fd5b505afa158015615381573d6000803e3d6000fd5b505050506040513d602081101561539757600080fd5b50519063ffffffff6132b816565b10156153e25760405162461bcd60e51b8152600401808060200182810382526027815260200180615b6d6027913960400191505060405180910390fd5b6153eb816112c1565b506000818152600960205260409020600c810154600d90910154111561544b576000818152600960205260409020600c810154600d909101546154339163ffffffff6133b416565b506000818152600960205260408120600c0155615487565b6000818152600960205260409020600d810154600c909101546154739163ffffffff6133b416565b506000818152600960205260408120600d01555b6000818152600960205260409020600d01541561551e576003546000828152600960205260408082208054600d9091015482516340c10f1960e01b81526001600160a01b039283166004820152602481019190915291519316926340c10f199260448084019391929182900301818387803b15801561550557600080fd5b505af1158015615519573d6000803e3d6000fd5b505050505b6000818152600960205260409020600c0154156155b5576001546000828152600960205260408082208054600c909101548251632770a7eb60e21b81526001600160a01b03928316600482015260248101919091529151931692639dc29fac9260448084019391929182900301818387803b15801561559c57600080fd5b505af11580156155b0573d6000803e3d6000fd5b505050505b60018054600083815260096020819052604080832080549581015492810154600e820154600f8301546010840154601185015460128601546013909601548751635f3f325b60e11b81526001600160a01b039c8d166004820152602481019990995260448901959095526064880193909352608487019190915260a486015260c485015260e484019190915261010483015251939092169263be7e64b69261012480820193929182900301818387803b15801561567157600080fd5b505af1158015615685573d6000803e3d6000fd5b5050506000828152600960208181526040928390208054600182015493820154600e830154600f8401546010850154601186015460128701546013880154600d890154600c909901548c516001600160a01b0390991689529988019a909a52868b01959095526060860193909352608085019190915260a084015260c083015260e082015261010081019390935261012083015261014082015290517f39cf7e0047b8651259e011d0b3ed8fc2c3dc2e49ed041f1651f06429698c1c949250908190036101600190a15056fe4d6f72706865725472616465456e67696e653a206c657665726167652065786365656473206d6178696d756d20616c6c6f776564206c657665726167652e4d6f72706865725472616465456e67696e653a204465616374697661746564206d61726b6574206f72646572206e6565647320616c6c2073686172657320746f20626520636c6f7365644d6f72706865725472616465456e67696e653a2043616e2774207061727469616c6c7920636c6f7365206120706f736974696f6e20616e64206f70656e20616e6f74686572206f6e6520696e206f70706f7369746520646972656374696f6e4d6f72706865725472616465456e67696e653a2072657175657374206578636565646564206d6178696d756d207065726d69747465642072657175657374732070657220626c6f636b2e4d6f72706865725472616465456e67696e653a20756e61626c6520746f2070726f636573732c206f7264657220646f6573206e6f742065786973742e4d6f72706865725472616465456e67696e653a2043616e277420636c6f7365206120706f736974696f6e2c206d61726b6574206e6f742061637469766520616e6420636c6f73696e67207072696365206e6f74206c6f636b65644d6f72706865725472616465456e67696e653a20756e61626c6520746f2070726f636573732c206f7264657220686173206265656e2064656c657465642e4f776e61626c653a207573652072656e6f756e6365206f776e65727368697020696e73746561642e4d6f72706865725472616465456e67696e653a206f6e6c792041646d696e6973747261746f72206f7220757365722063616e2063616e63656c20616e206f726465722e4d6f72706865725472616465456e67696e653a206d61726b6574207072696365206c6f776572207468656e206d61726b6574207370726561642e204f726465722063616e6e6f742062652070726f6365737365642e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774d6f72706865725472616465456e67696e653a2066756e6374696f6e2063616e206f6e6c792062652063616c6c6564206279204f7261636c6520436f6e74726163742e4d6f72706865725472616465456e67696e653a206d61726b657420756e6b6e6f776e206f722063757272656e746c79206e6f7420656e61626c656420666f722074726164696e672e4d6f72706865725472616465456e67696e653a206c6576657261676520746f6f20736d616c6c2e204c6576657261676520707265636973696f6e206973203165384d6f72706865725472616465456e67696e653a206d61726b657420707269636564206174207a65726f2e20427579206f726465722063616e6e6f742062652070726f6365737365642e4f776e61626c653a2063616c6c65722073686f756c64206265206f776e65722e4d6f72706865725472616465456e67696e653a20696e73756666696369656e742066756e64732ea265627a7a72315820cb9a00bd74f3aa4fa52897b6a4e7577ae149655caffe63aac6692578ab03023a64736f6c63430005100032

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

0000000000000000000000001f426c51f0ef7655a6f4c3eb58017d2f1c381bff00000000000000000000000051c5ce7c4926d5ca74f4824e11a062f1ef491762000000000000000000000000baf121d02e6948d3a089f99ddc522eb2a4a1b1fe0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d90c8a36fff52f1c8c05b54d4ce79610431ec0

-----Decoded View---------------
Arg [0] : _stateAddress (address): 0x1f426C51F0Ef7655A6f4c3Eb58017d2F1c381bfF
Arg [1] : _coldStorageOwnerAddress (address): 0x51c5cE7C4926D5cA74f4824e11a062f1Ef491762
Arg [2] : _stakingContractAddress (address): 0xBaF121D02E6948D3A089F99dDc522eb2A4a1b1fE
Arg [3] : _escrowOpenOrderEnabled (bool): True
Arg [4] : _deployedTimestampOverride (uint256): 0
Arg [5] : _mintingLimiterAddress (address): 0x30D90c8a36FFF52F1C8C05b54d4CE79610431Ec0

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000001f426c51f0ef7655a6f4c3eb58017d2f1c381bff
Arg [1] : 00000000000000000000000051c5ce7c4926d5ca74f4824e11a062f1ef491762
Arg [2] : 000000000000000000000000baf121d02e6948d3a089f99ddc522eb2a4a1b1fe
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [5] : 00000000000000000000000030d90c8a36fff52f1c8c05b54d4ce79610431ec0


Deployed Bytecode Sourcemap

587:46089:10:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;587:46089:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13089:696;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;13089:696:10;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1186:34;;;:::i;:::-;;;;;;;;;;;;;;;;;;6113:120;;;:::i;:::-;;;;-1:-1:-1;;;;;6113:120:10;;;;;;;;;;;;;;17086:2780;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;17086:2780:10;;;;;;;;;;;;;;;;;;;;;;:::i;996:25::-;;;:::i;:::-;;;;;;;;;;;;;;;;1298:81;;;:::i;21073:2386::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;21073:2386:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;42974:687::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;42974:687:10;;:::i;23465:2317::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;23465:2317:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;1027:26::-;;;:::i;12459:624::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;12459:624:10;;:::i;:::-;;;;-1:-1:-1;;;;;12459:624:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1098:82;;;:::i;26105:632::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;26105:632:10;;;;;;;;;;;;:::i;13791:379::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13791:379:10;;;;;;;:::i;:::-;;1482:137:11;;;:::i;5711:171:10:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5711:171:10;-1:-1:-1;;;;;5711:171:10;;:::i;43667:810::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;43667:810:10;;;;;;;;;;;;;;;;;;;:::i;5549:156::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5549:156:10;-1:-1:-1;;;;;5549:156:10;;:::i;682:77:11:-;;;:::i;1038:90::-;;;:::i;14176:242:10:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;14176:242:10;;:::i;9220:3018::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;9220:3018:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;6239:121::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;6239:121:10;;;;:::i;262:21:11:-;;;:::i;20177:539:10:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;20177:539:10;;;;;;-1:-1:-1;;;;;20177:539:10;;:::i;5888:219::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5888:219:10;-1:-1:-1;;;;;5888:219:10;;:::i;2498:184:11:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;2498:184:11;;;;;;;;:::i;1790:107::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1790:107:11;-1:-1:-1;;;;;1790:107:11;;:::i;1059:32:10:-;;;:::i;13089:696::-;13439:5;;:40;;;-1:-1:-1;;;13439:40:10;;-1:-1:-1;;;;;13439:40:10;;;;;;;;;;;;;;;13177:27;;;;;;;;;;;;13439:5;;:19;;:40;;;;;;;;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;13439:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;13439:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13439:40:10;13493:5;;:41;;;-1:-1:-1;;;13493:41:10;;-1:-1:-1;;;;;13493:41:10;;;;;;;;;;;;;;;:5;;;;;:20;;:41;;;;;13439:40;;13493:41;;;;;;;:5;:41;;;5:2:-1;;;;30:1;27;20:12;5:2;13493:41:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;13493:41:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13493:41:10;13548:5;;:43;;;-1:-1:-1;;;13548:43:10;;-1:-1:-1;;;;;13548:43:10;;;;;;;;;;;;;;;:5;;;;;:23;;:43;;;;;13493:41;;13548:43;;;;;;;:5;:43;;;5:2:-1;;;;30:1;27;20:12;5:2;13548:43:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;13548:43:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13548:43:10;13605:5;;:44;;;-1:-1:-1;;;13605:44:10;;-1:-1:-1;;;;;13605:44:10;;;;;;;;;;;;;;;:5;;;;;:24;;:44;;;;;13548:43;;13605:44;;;;;;;:5;:44;;;5:2:-1;;;;30:1;27;20:12;5:2;13605:44:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;13605:44:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13605:44:10;13663:5;;:46;;;-1:-1:-1;;;13663:46:10;;-1:-1:-1;;;;;13663:46:10;;;;;;;;;;;;;;;:5;;;;;:26;;:46;;;;;13605:44;;13663:46;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;13663:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;13663:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;13663:46:10;;;;;;;;;;;;;;;;13723:5;;;;;;;;;-1:-1:-1;;;;;13723:5:10;-1:-1:-1;;;;;13723:25:10;;13749:8;13758:9;13723:45;;;;;;;;;;;;;-1:-1:-1;;;;;13723:45:10;-1:-1:-1;;;;;13723:45:10;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;13723:45:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;13723:45:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13723:45:10;13419:359;;;;-1:-1:-1;13419:359:10;;-1:-1:-1;13419:359:10;-1:-1:-1;13419:359:10;-1:-1:-1;13723:45:10;;-1:-1:-1;13089:696:10;-1:-1:-1;;;13089:696:10:o;1186:34::-;;;-1:-1:-1;;;1186:34:10;;;;;:::o;6113:120::-;6202:5;;:24;;;-1:-1:-1;;;6202:24:10;;;;6161:22;;-1:-1:-1;;;;;6202:5:10;;:22;;:24;;;;;;;;;;;;;;:5;:24;;;5:2:-1;;;;30:1;27;20:12;5:2;6202:24:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;6202:24:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;6202:24:10;;-1:-1:-1;6113:120:10;:::o;17086:2780::-;17316:22;17352:23;17389:24;17427:25;17466:27;17507:25;5016:5;;;;;;;;;-1:-1:-1;;;;;5016:5:10;-1:-1:-1;;;;;5016:23:10;;:25;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5016:25:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5016:25:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5016:25:10;-1:-1:-1;;;;;5002:39:10;:10;:39;4994:119;;;;-1:-1:-1;;;4994:119:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17596:1;17561:16;;;:6;:16;;;;;:23;-1:-1:-1;;;;;17561:23:10;17553:112;;;;-1:-1:-1;;;17553:112:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17698:1;17683:12;:16;17675:102;;;;-1:-1:-1;;;17675:102:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17811:13;17795:12;:29;;17787:127;;;;-1:-1:-1;;;17787:127:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17933:16;;;;:6;:16;;;;;;;;;:28;;;:43;;;17986:29;;;:45;;;18041:26;;;:43;;;18094:37;;;:61;;;-1:-1:-1;18348:5:10;;18370:25;;;18348:48;;-1:-1:-1;;;18348:48:10;;-1:-1:-1;18348:48:10;;;;;;;;-1:-1:-1;;;;;18348:5:10;;;;:21;;:48;;;;;17933:16;18348:48;;;;;:5;:48;;;5:2:-1;;;;30:1;27;20:12;5:2;18348:48:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;18348:48:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;18348:48:10;18345:219;;18421:35;18447:8;18421:25;:35::i;:::-;18527:16;;;;:6;:16;;;;;:25;;;18501:52;;:25;:52::i;:::-;18470:16;;;;:6;:16;;;;;:28;;:83;18345:219;18678:5;;;;18699:16;;;:6;:16;;;;;;;;;:23;;18724:25;;;18678:72;;-1:-1:-1;;;18678:72:10;;-1:-1:-1;;;;;18699:23:10;;;18678:72;;;;;;;;;;;;;:5;;;;;:20;;:72;;;;;18699:16;;18678:72;;;;;;:5;:72;;;5:2:-1;;;;30:1;27;20:12;5:2;18678:72:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;18678:72:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;18678:72:10;18654:96;;18650:146;;;18766:19;18776:8;18766:9;:19::i;:::-;18811:23;18825:8;18811:13;:23::i;:::-;18849:16;;;;:6;:16;;;;;:31;;;;;18845:144;;;18896:25;18912:8;18896:15;:25::i;:::-;18845:144;;;18952:26;18969:8;18952:16;:26::i;:::-;18999:16;19018;;;:6;:16;;;;;;;;:23;;;19071:25;;;;-1:-1:-1;;;;;;19106:23:10;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;19106:23:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19144:344;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19018:23;19144:344;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;19018:23:10;;;;19144:344;;;;;;;;;19520:5;;:40;;;-1:-1:-1;;;19520:40:10;;-1:-1:-1;;;;;19520:40:10;;;;;;;;;;;;;;;:5;;;;;:19;;:40;;;;;;;;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;19520:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19520:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;19520:40:10;19574:5;;:41;;;-1:-1:-1;;;19574:41:10;;-1:-1:-1;;;;;19574:41:10;;;;;;;;;;;;;;;:5;;;;;:20;;:41;;;;;19520:40;;19574:41;;;;;;;:5;:41;;;5:2:-1;;;;30:1;27;20:12;5:2;19574:41:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19574:41:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;19574:41:10;19629:5;;:43;;;-1:-1:-1;;;19629:43:10;;-1:-1:-1;;;;;19629:43:10;;;;;;;;;;;;;;;:5;;;;;:23;;:43;;;;;19574:41;;19629:43;;;;;;;:5;:43;;;5:2:-1;;;;30:1;27;20:12;5:2;19629:43:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19629:43:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;19629:43:10;19686:5;;:44;;;-1:-1:-1;;;19686:44:10;;-1:-1:-1;;;;;19686:44:10;;;;;;;;;;;;;;;:5;;;;;:24;;:44;;;;;19629:43;;19686:44;;;;;;;:5;:44;;;5:2:-1;;;;30:1;27;20:12;5:2;19686:44:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19686:44:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;19686:44:10;19744:5;;:46;;;-1:-1:-1;;;19744:46:10;;-1:-1:-1;;;;;19744:46:10;;;;;;;;;;;;;;;:5;;;;;:26;;:46;;;;;19686:44;;19744:46;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;19744:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19744:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;19744:46:10;19804:5;;:45;;;-1:-1:-1;;;19804:45:10;;-1:-1:-1;;;;;19804:45:10;;;;;;;;;;;;;;;:5;;;;;:25;;:45;;;;;19744:46;;19804:45;;;;;;;:5;:45;;;5:2:-1;;;;30:1;27;20:12;5:2;19804:45:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19804:45:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;19804:45:10;19499:360;;-1:-1:-1;19499:360:10;;-1:-1:-1;19499:360:10;;-1:-1:-1;19499:360:10;-1:-1:-1;19499:360:10;-1:-1:-1;19804:45:10;-1:-1:-1;;;17086:2780:10;;;;;;;;;;;:::o;996:25::-;;;;:::o;1298:81::-;;;-1:-1:-1;;;;;1298:81:10;;:::o;21073:2386::-;21363:19;21419:21;21477:24;985:5;21516:36;;21512:216;;;-1:-1:-1;985:5:10;21512:216;21741:14;21737:276;;-1:-1:-1;21905:12:10;;-1:-1:-1;21988:14:10;21737:276;22126:12;22039:83;22059:13;22074:16;22092:5;22099:22;22039:19;:83::i;:::-;:99;22022:1396;;22215:1;22201:15;;22022:1396;;;22367:67;985:5;22367:52;22386:31;985:5;22400:16;22386:31;:13;:31;:::i;:::-;22367:13;;:52;:17;:52;:::i;:::-;:56;:67;:56;:67;:::i;:::-;22353:81;-1:-1:-1;22462:66:10;22478:49;985:5;22478:34;:12;22495:16;22478:34;:16;:34;:::i;:49::-;22462:11;;:66;:15;:66;:::i;:::-;22448:80;-1:-1:-1;22555:4:10;22546:13;;;;22542:866;;;22795:67;22811:50;985:5;22811:35;:13;22829:16;22811:35;:17;:35;:::i;22795:67::-;22781:81;;22880:23;22906:80;22930:13;22945:16;22963:22;22906:23;:80::i;:::-;22880:106;;23027:11;23008:15;:30;23004:185;;23076:32;:11;23092:15;23076:32;:15;:32;:::i;:::-;23062:46;;23004:185;;;23169:1;23155:15;;23004:185;22542:866;;;;23328:65;23344:48;985:5;23344:33;:13;23362:14;23344:33;:17;:33;:::i;:48::-;23328:11;;:65;:15;:65;:::i;:::-;23314:79;;22542:866;-1:-1:-1;;21073:2386:10;;;;;;;;;:::o;42974:687::-;43040:25;43077:16;;;:6;:16;;;;;:36;;;:40;;;43131:30;;;:34;43127:232;;43240:16;;;;:6;:16;;;;;;;;:34;;;;43276:37;;;;43321:26;;;;;43220:128;;43240:34;43276:37;43315:4;;43220:19;:128::i;:::-;43181:16;;;;:6;:16;;;;;:36;;:167;43127:232;43406:1;43372:16;;;:6;:16;;;;;:31;;;:35;43368:234;;43482:16;;;;:6;:16;;;;;;;:34;;;;43518:37;;;;43564:26;;;;;43462:129;;43482:16;43462:19;:129::i;:::-;43423:16;;;;:6;:16;;;;;:36;;:168;43368:234;-1:-1:-1;43618:16:10;;;;:6;:16;;;;;:36;;;;42974:687::o;23465:2317::-;23754:19;23810:21;23868:24;985:5;23907:36;;23903:216;;;-1:-1:-1;985:5:10;23903:216;24132:14;24128:274;;-1:-1:-1;24294:12:10;;-1:-1:-1;24377:14:10;24128:274;24444:82;24464:13;24479:16;24497:4;24503:22;24444:19;:82::i;:::-;24428:12;:98;24411:1337;;24603:1;24589:15;;24411:1337;;;24649:65;985:5;24649:50;24667:31;:16;985:5;24667:31;:20;:31;:::i;24649:65::-;24635:79;-1:-1:-1;24862:68:10;24635:79;24863:49;985:5;24863:34;:12;24880:16;24863:34;:16;:34;:::i;:49::-;24862:55;:68;:55;:68;:::i;1027:26::-;;;;:::o;12459:624::-;12525:15;12774:16;;;:6;:16;;;;;:23;;;12811:25;;;12850:34;;;;12898:35;;;;12947:28;;;;12989:29;;;;13032:30;;;;;-1:-1:-1;;;;;12774:23:10;;;;12811:25;;12850:34;;12898:35;;12947:28;;12989:29;13032:30;12459:624::o;1098:82::-;;;-1:-1:-1;;;;;1098:82:10;;:::o;26105:632::-;26314:17;;26240:23;;26279:32;:22;26306:4;26279:32;:26;:32;:::i;:::-;:52;26275:135;;;26372:17;;:27;;26394:4;26372:27;:21;:27;:::i;:::-;26347:52;;26275:135;26437:50;26455:31;:16;985:5;26455:31;:20;:31;:::i;26437:50::-;26419:68;-1:-1:-1;26515:82:10;26535:61;26594:1;26536:52;26582:5;26536:41;26544:32;:22;26571:4;26544:32;:26;:32;:::i;:::-;26536:3;;:41;:7;:41;:::i;:52::-;26535:58;:61;:58;:61;:::i;:::-;26515:15;;:82;:19;:82;:::i;:::-;26497:100;;26625:73;985:5;26625:58;985:5;26625:43;26645:7;;;;;;;;;-1:-1:-1;;;;;26645:7:10;-1:-1:-1;;;;;26645:20:10;;:22;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;26645:22:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;26645:22:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;26645:22:10;26625:15;;:43;:19;:43;:::i;:73::-;26607:91;26105:632;-1:-1:-1;;;;26105:632:10:o;13791:379::-;5016:5;;;;;;;;;-1:-1:-1;;;;;5016:5:10;-1:-1:-1;;;;;5016:23:10;;:25;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5016:25:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5016:25:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5016:25:10;-1:-1:-1;;;;;5002:39:10;:10;:39;4994:119;;;;-1:-1:-1;;;4994:119:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13890:5;;13921:21;;-1:-1:-1;;;;;13890:5:10;;;;:17;;13921:21;13956:9;13979:13;:3;13987:4;13979:13;:7;:13;:::i;:::-;13890:207;;;-1:-1:-1;;;;;;13890:207:10;;;;;;;-1:-1:-1;;;;;13890:207:10;;;;;;;;;;;;;;;;;;14006:1;13890:207;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14006:1;13890:207;;;;5:2:-1;;;;30:1;27;20:12;5:2;13890:207:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;14113:49:10;;;;;;;;;;;;;;;;-1:-1:-1;14113:49:10;;;;;;;;-1:-1:-1;14113:49:10;13791:379;;:::o;1482:137:11:-;886:9;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:11;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:11;;;;;;;;;;;;;;;1580:1;1564:6;;1543:40;;-1:-1:-1;;;;;1564:6:11;;;;1543:40;;1580:1;;1543:40;1610:1;1593:19;;-1:-1:-1;;;;;;1593:19:11;;;1482:137::o;5711:171:10:-;886:9:11;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:11;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:11;;;;;;;;;;;;;;;5790:7:10;:42;;-1:-1:-1;;;;;5790:42:10;;-1:-1:-1;;;;;;5790:42:10;;;;;;;;5847:28;;;;;;;;;;;;;;;;5711:171;:::o;43667:810::-;43817:25;43867:4;43858:13;;;;43854:583;;;43907:87;43972:21;43907:60;43930:36;43972:21;985:5;43930:36;:25;:36;:::i;:::-;43907:18;;:60;:22;:60;:::i;:87::-;43887:107;;44028:113;44050:90;44074:18;44094:21;44117:22;44050:23;:90::i;:::-;44028:17;;:113;:21;:113;:::i;:::-;44008:133;;43854:583;;;44192:87;44257:21;44192:60;44215:36;44257:21;985:5;44215:36;:25;:36;:::i;44192:87::-;44172:107;;44313:113;44335:90;44359:18;44379:21;44402:22;44335:23;:90::i;:::-;44313:17;;:113;:21;:113;:::i;:::-;44293:133;43667:810;-1:-1:-1;;;;;43667:810:10:o;5549:156::-;886:9:11;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:11;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:11;;;;;;;;;;;;;;;5624:5:10;:35;;-1:-1:-1;;;;;5624:35:10;;-1:-1:-1;;;;;;5624:35:10;;;;;;;;5674:24;;;;;;;;;;;;;;;;5549:156;:::o;682:77:11:-;720:7;746:6;-1:-1:-1;;;;;746:6:11;682:77;:::o;1038:90::-;1078:4;1115:6;-1:-1:-1;;;;;1115:6:11;1101:10;:20;;1038:90::o;14176:242:10:-;14316:5;;14334:21;;14316:51;;;-1:-1:-1;;;14316:51:10;;-1:-1:-1;;;;;14334:21:10;;;14316:51;;;;;;;;;;;;14250:7;;;;14316:5;;:17;;:51;;;;;;;;;;;;;;:5;:51;;;5:2:-1;;;;30:1;27;20:12;5:2;14316:51:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;14316:51:10;;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;14316:51:10;;;;14176:242;-1:-1:-1;;;14176:242:10:o;9220:3018::-;5016:5;;:25;;;-1:-1:-1;;;5016:25:10;;;;9469:16;;-1:-1:-1;;;;;5016:5:10;;:23;;:25;;;;;;;;;;;;;;:5;:25;;;5:2:-1;;;;30:1;27;20:12;5:2;5016:25:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5016:25:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5016:25:10;-1:-1:-1;;;;;5002:39:10;:10;:39;4994:119;;;;-1:-1:-1;;;4994:119:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;985:5;9518:14;:27;;9510:105;;;;-1:-1:-1;;;9510:105:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9651:5;;;;;;;;;-1:-1:-1;;;;;9651:5:10;-1:-1:-1;;;;;9651:24:10;;:26;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9651:26:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;9651:26:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;9651:26:10;9633:44;;;9625:119;;;;-1:-1:-1;;;9625:119:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9755:114;9791:8;9801:9;9812:18;9832:19;9853:15;9755:35;:114::i;:::-;9952:5;;;;;;;;;-1:-1:-1;;;;;9952:5:10;-1:-1:-1;;;;;9952:30:10;;:32;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9952:32:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;9952:32:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;9952:32:10;9913:5;;:35;;;-1:-1:-1;;;9913:35:10;;-1:-1:-1;;;;;9913:35:10;;;;;;;;;:5;;;;;:25;;:35;;;;;9952:32;;9913:35;;;;;;;:5;:35;;;5:2:-1;;;;30:1;27;20:12;5:2;9913:35:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;9913:35:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;9913:35:10;:71;;;:137;;-1:-1:-1;10000:5:10;;:35;;;-1:-1:-1;;;10000:35:10;;-1:-1:-1;;;;;10000:35:10;;;;;;;;;10038:12;;10000:5;;;;;:25;;:35;;;;;;;;;;;;;;;:5;:35;;;5:2:-1;;;;30:1;27;20:12;5:2;10000:35:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;10000:35:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;10000:35:10;:50;9913:137;9905:245;;;;-1:-1:-1;;;9905:245:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10271:23;;10268:532;;10313:15;10310:480;;;10401:5;;:41;;;-1:-1:-1;;;10401:41:10;;-1:-1:-1;;;;;10401:41:10;;;;;;;;;;;;;;;:5;;;;;:20;;:41;;;;;;;;;;;;;;:5;:41;;;5:2:-1;;;;30:1;27;20:12;5:2;10401:41:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;10401:41:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;10401:41:10;10379:63;;10371:171;;;;-1:-1:-1;;;10371:171:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10310:480;;;10635:5;;:40;;;-1:-1:-1;;;10635:40:10;;-1:-1:-1;;;;;10635:40:10;;;;;;;;;;;;;;;:5;;;;;:19;;:40;;;;;;;;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;10635:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;10635:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;10635:40:10;10613:62;;10605:170;;;;-1:-1:-1;;;10605:170:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10810:5;;:35;;;-1:-1:-1;;;10810:35:10;;-1:-1:-1;;;;;10810:35:10;;;;;;;;;:5;;;;;:25;;:35;;;;;:5;;:35;;;;;;;:5;;:35;;;5:2:-1;;;;30:1;27;20:12;5:2;10810:35:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;10855:5:10;;:40;;;-1:-1:-1;;;10855:40:10;;-1:-1:-1;;;;;10855:40:10;;;;;;;;;:5;;;;;-1:-1:-1;10855:30:10;;-1:-1:-1;10855:40:10;;;;;:5;;:40;;;;;;;:5;;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;10855:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;10855:40:10;;;;10905:10;;:12;;;;;;;;;;;;;10995:8;11021:12;11051:9;11078:18;11114:19;11151:15;11184:14;11216:10;;10961:283;;;;;;-1:-1:-1;;;;;10961:283:10;-1:-1:-1;;;;;10961:283:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;10961:283:10;;;10938:320;;;;;;10927:331;;11282:8;11268:11;:22;;;;11326:8;11300:6;:16;11307:8;11300:16;;;;;;;;;;;:23;;;:34;;;;;-1:-1:-1;;;;;11300:34:10;;;;;-1:-1:-1;;;;;11300:34:10;;;;;;11372:9;11344:6;:16;11351:8;11344:16;;;;;;;;;;;:25;;:37;;;;11428:18;11391:6;:16;11398:8;11391:16;;;;;;;;;;;:34;;:55;;;;11494:19;11456:6;:16;11463:8;11456:16;;;;;;;;;;;:35;;:57;;;;11557:15;11523:6;:16;11530:8;11523:16;;;;;;;;;;;:31;;;:49;;;;;;;;;;;;;;;;;;11615:14;11582:6;:16;11589:8;11582:16;;;;;;;;;;;:30;;:47;;;;11718:9;11696:8;-1:-1:-1;;;;;11644:215:10;;11674:8;11741:18;11773:19;11806:15;11835:14;11644:215;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12161:44;12175:8;12185:19;12161:13;:44::i;:::-;9220:3018;;;;;;;;:::o;6239:121::-;886:9:11;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:11;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:11;;;;;;;;;;;;;;;6318:22:10;:35;;;;;-1:-1:-1;;;6318:35:10;-1:-1:-1;;;;6318:35:10;;;;;;;;;6239:121::o;262:21:11:-;;;-1:-1:-1;;;;;262:21:11;;:::o;20177:539:10:-;5016:5;;;;;;;;;-1:-1:-1;;;;;5016:5:10;-1:-1:-1;;;;;5016:23:10;;:25;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5016:25:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5016:25:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5016:25:10;-1:-1:-1;;;;;5002:39:10;:10;:39;4994:119;;;;-1:-1:-1;;;4994:119:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20282:16;;;;:6;:16;;;;;:23;-1:-1:-1;;;;;20270:35:10;;;20282:23;;20270:35;;:69;;;20321:18;:16;:18::i;:::-;-1:-1:-1;;;;;20309:30:10;:8;-1:-1:-1;;;;;20309:30:10;;20270:69;20262:149;;;;-1:-1:-1;;;20262:149:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20464:1;20429:16;;;:6;:16;;;;;:23;-1:-1:-1;;;;;20429:23:10;20421:110;;;;-1:-1:-1;;;20421:110:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20603:23;20617:8;20603:13;:23::i;:::-;20644:16;;;;:6;:16;;;;;;;;20637:23;;-1:-1:-1;;;;;;20637:23:10;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;20637:23:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20675:34;-1:-1:-1;;;;;20675:34:10;;;20651:8;;20675:34;;20644:16;20675:34;20177:539;;:::o;5888:219::-;886:9:11;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:11;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:11;;;;;;;;;;;;;;;5981:14:10;:62;;-1:-1:-1;;;;;5981:62:10;;-1:-1:-1;;;;;;5981:62:10;;;;;;;;6058:42;;;;;;;;;;;;;;;;5888:219;:::o;2498:184:11:-;2595:13;886:9;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:11;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:11;;;;;;;;;;;;;;;2634:13;-1:-1:-1;;;;;2627:30:11;;2658:7;:5;:7::i;:::-;2667;2627:48;;;;;;;;;;;;;-1:-1:-1;;;;;2627:48:11;-1:-1:-1;;;;;2627:48:11;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2627:48:11;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;2627:48:11;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;2627:48:11;;-1:-1:-1;942:1:11;2498:184;;;;:::o;1790:107::-;886:9;:7;:9::i;:::-;878:54;;;;;-1:-1:-1;;;878:54:11;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;878:54:11;;;;;;;;;;;;;;;1862:28;1881:8;1862:18;:28::i;:::-;1790:107;:::o;1059:32:10:-;;;;:::o;8494:278::-;8608:16;;;;:6;:16;;;;;:23;;;8633:25;;;8660:34;;;;8696:35;;;;8733:31;;;;;8572:193;;-1:-1:-1;;;;;8608:23:10;;;;8696:35;8733:31;;8572:35;:193::i;14763:1753::-;14818:16;14837;;;:6;:16;;;;;;;;;:23;;;14890:25;;;;14957:37;;;;;15032:5;;:41;;-1:-1:-1;;;15032:41:10;;-1:-1:-1;;;;;14837:23:10;;;15032:41;;;;;;;;;;;;;;14890:25;;14957:37;;15032:5;;;;;:20;;:41;;;;;14837:16;;15032:41;;;;;:5;:41;;;5:2:-1;;;;30:1;27;20:12;5:2;15032:41:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;15032:41:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15032:41:10;15008:65;;15004:1506;;;15093:5;;:39;;;-1:-1:-1;;;15093:39:10;;-1:-1:-1;;;;;15093:39:10;;;;;;;;;;;;;;;15135:1;;15093:5;;;;;:19;;:39;;;;;;;;;;;;;;;:5;:39;;;5:2:-1;;;;30:1;27;20:12;5:2;15093:39:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;15093:39:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15093:39:10;:43;15089:690;;;15156:5;;;15256:16;;;:6;:16;;;;;;;;:26;;;;15327:41;;-1:-1:-1;;;15327:41:10;;-1:-1:-1;;;;;15327:41:10;;;;;;;;;;;;;;;15156:5;;;;;:17;;15195:8;;15225:9;;15156:5;;;;15327:20;;:41;;;;;;;;;;15156:5;15327:41;;;5:2:-1;;;;30:1;27;20:12;5:2;15327:41:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;15327:41:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15327:41:10;15156:313;;;-1:-1:-1;;;;;;15156:313:10;;;;;;;-1:-1:-1;;;;;15156:313:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15390:1;15156:313;;;;;;;;;;;;985:5;15156:313;;;;;;;;;;;;;;;;;;;;;;15390:1;15156:313;;;;5:2:-1;;;;30:1;27;20:12;5:2;15156:313:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;15619:16:10;;;;:6;:16;;;;;;;;;:26;;;;15667:28;;;;15717:29;;;;;15492:272;;15593:4;15492:272;;;;;;;;;;;;;;;;;;;;;;;;;15562:9;;-1:-1:-1;;;;;;15492:272:10;;;;;;;;;;;;;15089:690;15796:5;;:40;;;-1:-1:-1;;;15796:40:10;;-1:-1:-1;;;;;15796:40:10;;;;;;;;;;;;;;;15839:1;;15796:5;;;;;:20;;:40;;;;;;;;;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;15796:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;15796:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15796:40:10;:44;15792:708;;;15860:5;;;15960:16;;;:6;:16;;;;;;;;;:26;;;;16008:40;;-1:-1:-1;;;16008:40:10;;-1:-1:-1;;;;;16008:40:10;;;;;;;;;;;;;;;15860:5;;;;;:17;;15899:8;;15929:9;;15960:26;15860:5;;16008:19;;:40;;;;;15960:16;;16008:40;;;;;;15860:5;16008:40;;;5:2:-1;;;;30:1;27;20:12;5:2;16008:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;16008:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;16008:40:10;15860:329;;;-1:-1:-1;;;;;;15860:329:10;;;;;;;-1:-1:-1;;;;;15860:329:10;;;;;;;;;;;;;;;;;;;;;;;;;16070:1;15860:329;;;;;;;;;;;;;;;;;;985:5;15860:329;;;;;;;;;;;;;;;;;;;;;;16070:1;15860:329;;;;5:2:-1;;;;30:1;27;20:12;5:2;15860:329:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;16313:5:10;16340:16;;;:6;:16;;;;;;;;:26;;;;16388:28;;;;16438:29;;;;;16212:273;;;;;;;;;;;;;;;;;;;;;16282:9;;-1:-1:-1;;;;;;16212:273:10;;;;;;;;;;;;;15792:708;14763:1753;;;;:::o;6370:454::-;6547:1;6510:16;;;:6;:16;;;;;:34;;;:38;6507:311;;6605:21;6629:16;;;:6;:16;;;;;;:34;;;;;6677:38;;;;-1:-1:-1;6729:5:10;6744:22;;6768:23;;6729:78;;-1:-1:-1;;;6729:78:10;;-1:-1:-1;;;;;6744:22:10;;;6729:78;;;;6768:23;;;6729:78;;;;;;;;;;;;6629:34;;6729:5;;;:14;;:78;;;;;6605:21;;6729:78;;;;;6605:21;6729:5;:78;;;5:2:-1;;;;30:1;27;20:12;5:2;6729:78:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;6729:78:10;;;;6507:311;6370:454;:::o;27199:1788::-;27301:1;27264:16;;;:6;:16;;;;;:34;;;:38;27260:695;;27516:5;;;;27537:16;;;:6;:16;;;;;;;;;:23;;27562:25;;;27516:72;;-1:-1:-1;;;27516:72:10;;-1:-1:-1;;;;;27537:23:10;;;27516:72;;;;;;;;;;;;;:5;;;;;:20;;:72;;;;;27537:16;;27516:72;;;;;;:5;:72;;;5:2:-1;;;;30:1;27;20:12;5:2;27516:72:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;27516:72:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;27516:72:10;27478:16;;;;:6;27516:72;27478:16;;;;:34;;;:110;27474:471;;27697:16;;;;:6;:16;;;;;:34;;;;27661:33;;;;:70;27474:471;;;27858:5;;;;27879:16;;;:6;:16;;;;;;;;;:23;;27904:25;;;27858:72;;-1:-1:-1;;;27858:72:10;;-1:-1:-1;;;;;27879:23:10;;;27858:72;;;;;;;;;;;;;:5;;;;;:20;;:72;;;;;27879:16;;27858:72;;;;;;:5;:72;;;5:2:-1;;;;30:1;27;20:12;5:2;27858:72:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;27858:72:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;27858:72:10;27822:16;;;;:6;27858:72;27822:16;;;;:33;;:108;27474:471;28146:5;;;;28167:16;;;:6;:16;;;;;;;;;:23;;28192:25;;;28146:72;;-1:-1:-1;;;28146:72:10;;-1:-1:-1;;;;;28167:23:10;;;28146:72;;;;;;;;;;;;;:5;;;;;:20;;:72;;;;;28167:16;;28146:72;;;;;;:5;:72;;;5:2:-1;;;;30:1;27;20:12;5:2;28146:72:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;28146:72:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;28146:72:10;28109:16;;;;:6;28146:72;28109:16;;;;:33;;;:109;:165;;;;-1:-1:-1;28273:1:10;28235:16;;;:6;:16;;;;;:35;;;:39;;28109:165;28093:645;;;28427:16;;;;:6;:16;;;;;:28;;;;28477:30;;;;28604:29;;;;;28334:393;;28391:335;;28477:30;28529:3;;28427:28;;28604:29;28477:30;;28391:14;:335::i;:::-;28334:16;;;;:6;:16;;;;;:35;;;;:393;:39;:393;:::i;:::-;28299:16;;;;:6;:16;;;;;:32;;:428;28093:645;28839:1;28803:16;;;:6;:16;;;;;:33;;;:37;28799:88;;28856:20;28867:8;28856:10;:20::i;:::-;28935:1;28900:16;;;:6;:16;;;;;:32;;;:36;28896:85;;28952:18;28961:8;28952;:18::i;29450:1685::-;29553:1;29516:16;;;:6;:16;;;;;:34;;;:38;29512:688;;29767:5;;;;29787:16;;;:6;:16;;;;;;;;;:23;;29812:25;;;29767:71;;-1:-1:-1;;;29767:71:10;;-1:-1:-1;;;;;29787:23:10;;;29767:71;;;;;;;;;;;;;:5;;;;;:19;;:71;;;;;29787:16;;29767:71;;;;;;:5;:71;;;5:2:-1;;;;30:1;27;20:12;5:2;29767:71:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;29767:71:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;29767:71:10;29729:16;;;;:6;29767:71;29729:16;;;;:34;;;:109;29725:465;;29945:16;;;;:6;:16;;;;;:34;;;;29910:32;;;;:69;29725:465;;;30104:5;;;;30124:16;;;:6;:16;;;;;;;;;:23;;30149:25;;;30104:71;;-1:-1:-1;;;30104:71:10;;-1:-1:-1;;;;;30124:23:10;;;30104:71;;;;;;;;;;;;;:5;;;;;:19;;:71;;;;;30124:16;;30104:71;;;;;;:5;:71;;;5:2:-1;;;;30:1;27;20:12;5:2;30104:71:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;30104:71:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;30104:71:10;30069:16;;;;:6;30104:71;30069:16;;;;:32;;:106;29725:465;30262:5;;;;30282:16;;;:6;:16;;;;;;;;;:23;;30307:25;;;30262:71;;-1:-1:-1;;;30262:71:10;;-1:-1:-1;;;;;30282:23:10;;;30262:71;;;;;;;;;;;;;:5;;;;;:19;;:71;;;;;30282:16;;30262:71;;;;;;:5;:71;;;5:2:-1;;;;30:1;27;20:12;5:2;30262:71:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;30262:71:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;30262:71:10;30226:16;;;;:6;30262:71;30226:16;;;;:32;;;:107;:163;;;;-1:-1:-1;30388:1:10;30350:16;;;:6;:16;;;;;:35;;;:39;;30226:163;30210:677;;;30548:16;;;;:6;:16;;;;;:28;;;;30602:30;;;;30741:29;;;;;30446:430;;30507:368;;30602:30;30658:3;;30548:28;;30741:29;30602:30;;30507:15;:368::i;30446:430::-;30410:16;;;;:6;:16;;;;;:33;;:466;30210:677;30986:1;30951:16;;;:6;:16;;;;;:32;;;:36;30947:86;;31003:19;31013:8;31003:9;:19::i;:::-;31082:1;31046:16;;;:6;:16;;;;;:33;;;:37;31042:87;;31099:19;31109:8;31099:9;:19::i;834:176:12:-;892:7;923:5;;;946:6;;;;938:46;;;;;-1:-1:-1;;;938:46:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;1002:1;834:176;-1:-1:-1;;;834:176:12:o;2159:459::-;2217:7;2458:6;2454:45;;-1:-1:-1;2487:1:12;2480:8;;2454:45;2521:5;;;2525:1;2521;:5;:1;2544:5;;;;;:10;2536:56;;;;-1:-1:-1;;;2536:56:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3073:130;3131:7;3157:39;3161:1;3164;3157:39;;;;;;;;;;;;;;;;;:3;:39::i;1274:134::-;1332:7;1358:43;1362:1;1365;1358:43;;;;;;;;;;;;;;;;;:3;:43::i;7136:1312:10:-;7368:23;;7365:1077;;7415:5;;:32;;;-1:-1:-1;;;7415:32:10;;;;;;;;;;-1:-1:-1;;;;;7415:5:10;;;;:21;;:32;;;;;;;;;;;;;;;:5;:32;;;5:2:-1;;;;30:1;27;20:12;5:2;7415:32:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;7415:32:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;7415:32:10;:40;;7451:4;7415:40;7407:125;;;;-1:-1:-1;;;7407:125:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7365:1077;;;7734:5;;:32;;;-1:-1:-1;;;7734:32:10;;;;;;;;;;-1:-1:-1;;;;;7734:5:10;;;;:21;;:32;;;;;;;;;;;;;;;:5;:32;;;5:2:-1;;;;30:1;27;20:12;5:2;7734:32:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;7734:32:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;7734:32:10;7731:701;;7842:1;7803:36;7829:9;7803:25;:36::i;:::-;:40;7795:143;;;;-1:-1:-1;;;7795:143:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7959:15;7956:462;;;8055:5;;:41;;;-1:-1:-1;;;8055:41:10;;-1:-1:-1;;;;;8055:41:10;;;;;;;;;;;;;;;:5;;;;;:20;;:41;;;;;;;;;;;;;;:5;:41;;;5:2:-1;;;;30:1;27;20:12;5:2;8055:41:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;8055:41:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;8055:41:10;8033:63;;8025:150;;;;-1:-1:-1;;;8025:150:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7956:462;8280:5;;:40;;;-1:-1:-1;;;8280:40:10;;-1:-1:-1;;;;;8280:40:10;;;;;;;;;;;;;;;:5;;;;;:19;;:40;;;;;;;;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;8280:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;8280:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;8280:40:10;8258:62;;8250:149;;;;-1:-1:-1;;;8250:149:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7136:1312;;;;;:::o;6830:299::-;6914:22;;-1:-1:-1;;;6914:22:10;;;;:42;;;;;6955:1;6940:12;:16;6914:42;6911:212;;;6972:5;;;6987:16;;;:6;:16;;;;;;:23;7012:22;;6972:77;;-1:-1:-1;;;6972:77:10;;-1:-1:-1;;;;;6987:23:10;;;6972:77;;;;7012:22;;;6972:77;;;;;;;;;;;;:5;;;:14;;:77;;;;;:5;;:77;;;;;;:5;;:77;;;5:2:-1;;;;30:1;27;20:12;5:2;6972:77:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;7063:16:10;;;;:6;:16;;;;;:34;;:49;;;-1:-1:-1;6911:212:10;6830:299;;:::o;2041:227:11:-;-1:-1:-1;;;;;2114:22:11;;2106:75;;;;-1:-1:-1;;;2106:75:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2217:6;;;2196:38;;-1:-1:-1;;;;;2196:38:11;;;;2217:6;;;2196:38;;;2244:6;:17;;-1:-1:-1;;;;;;2244:17:11;-1:-1:-1;;;;;2244:17:11;;;;;;;;;;2041:227::o;38161:1555:10:-;38217:15;38235:16;;;:6;:16;;;;;;;;:23;;;38288:25;;;;38491:33;;;;;38446:5;;:40;;-1:-1:-1;;;38446:40:10;;-1:-1:-1;;;;;38235:23:10;;;38446:40;;;;;;;;;;;;;;38235:23;;38288:25;;38217:15;;;;;;;;38446:79;;38491:33;;38446:5;;;:20;;:40;;;;;38235:16;;38446:40;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;38446:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;38446:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;38446:40:10;;:79;:44;:79;:::i;:::-;38420:105;;38535:18;38556:28;38575:8;38556:18;:28::i;:::-;38644:5;;:40;;;-1:-1:-1;;;38644:40:10;;-1:-1:-1;;;;;38644:40:10;;;;;;;;;;;;;;;38535:49;;-1:-1:-1;38644:5:10;;;:20;;:40;;;;;;;;;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;38644:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;38644:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;38644:40:10;38607:16;;;;:6;38644:40;38607:16;;;;:33;;;:77;38603:615;;;38716:1;38700:17;;38748:1;38731:18;;985:5;38760:28;;38603:615;;;38835:5;;:43;;;-1:-1:-1;;;38835:43:10;;-1:-1:-1;;;;;38835:43:10;;;;;;;;;;;;;;;:5;;;;;:23;;:43;;;;;;;;;;;;;;:5;:43;;;5:2:-1;;;;30:1;27;20:12;5:2;38835:43:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;38835:43:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;38835:43:10;38906:5;;:44;;;-1:-1:-1;;;38906:44:10;;-1:-1:-1;;;;;38906:44:10;;;;;;;;;;;;;;;38835:43;;-1:-1:-1;38906:5:10;;;:24;;:44;;;;;38835:43;;38906:44;;;;;;;;:5;:44;;;5:2:-1;;;;30:1;27;20:12;5:2;38906:44:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;38906:44:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;38906:44:10;38980:5;;:46;;;-1:-1:-1;;;38980:46:10;;-1:-1:-1;;;;;38980:46:10;;;;;;;;;;;;;;;38906:44;;-1:-1:-1;38980:5:10;;;:26;;:46;;;;;38906:44;;38980:46;;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;38980:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;38980:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;38980:46:10;;-1:-1:-1;39163:44:10;39198:8;39163:34;:44::i;:::-;39259:1;39228:16;;;:6;:16;;;;;;;;:28;;;:32;;;;39270:26;;;:39;;;39352:5;;;39372:23;;39397:25;;;;;39352:71;;-1:-1:-1;;;39352:71:10;;-1:-1:-1;;;;;39372:23:10;;;39352:71;;;;;;;;;;;;;:5;;;:19;;:71;;;;;39228:16;;39352:71;;;;;;:5;:71;;;5:2:-1;;;;30:1;27;20:12;5:2;39352:71:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;39352:71:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;39352:71:10;39319:16;;;;:6;39352:71;39319:16;;;;:30;;;:104;;;;39433:31;;;:49;;;39492:34;;;:50;;;39552:35;;;:52;;;39614:37;;:56;;;39681:28;39326:8;39681:18;:28::i;:::-;38161:1555;;;;;;;;:::o;31499:2848::-;31553:15;31571:16;;;:6;:16;;;;;;;;:23;;;31624:25;;;;32062:5;;:46;;-1:-1:-1;;;32062:46:10;;-1:-1:-1;;;;;31571:23:10;;;32062:46;;;;;;;;;;;;;;31571:23;;31624:25;;31553:15;;;;;;32062:5;;;;:26;;:46;;;;;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;32062:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;32062:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;32062:46:10;;-1:-1:-1;985:5:10;32122:29;;32118:89;;;-1:-1:-1;985:5:10;32118:89;32236:32;:17;985:5;32236:32;:21;:32;:::i;:::-;32369:16;;;;:6;:16;;;;;;;;;:28;;;32320:5;;:43;;-1:-1:-1;;;32320:43:10;;-1:-1:-1;;;;;32320:43:10;;;;;;;;;;;;;;;32216:52;;-1:-1:-1;32298:100:10;;32369:28;;32298:66;;32320:5;;;:23;;:43;;;;;32369:16;;32320:43;;;;;;:5;:43;;;5:2:-1;;;;30:1;27;20:12;5:2;32320:43:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;32320:43:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;32320:43:10;32298:17;;:66;:21;:66;:::i;:100::-;32412:5;;:46;;;-1:-1:-1;;;32412:46:10;;-1:-1:-1;;;;;32412:46:10;;;;;;;;;;;;;;;32278:120;;-1:-1:-1;32278:120:10;;32412:5;;;;;:26;;:46;;;;;;;;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;32412:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;32412:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;32412:46:10;:66;32408:238;;;32514:5;;:46;;;-1:-1:-1;;;32514:46:10;;-1:-1:-1;;;;;32514:46:10;;;;;;;;;;;;;;;:69;;32565:17;;32514:5;;:26;;:46;;;;;;;;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;32514:69:10;32494:89;;32408:238;;;-1:-1:-1;32634:1:10;32408:238;32708:5;;:39;;;-1:-1:-1;;;32708:39:10;;-1:-1:-1;;;;;32708:39:10;;;;;;;;;;;;;;;32656:27;;32686:77;;985:5;;32686:62;;32708:5;;;;;:19;;:39;;;;;;;;;;;;;;:5;:39;;;5:2:-1;;;;30:1;27;20:12;5:2;32708:39:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;32708:39:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;32708:39:10;32686:17;;:62;:21;:62;:::i;:77::-;32892:5;;:46;;;-1:-1:-1;;;32892:46:10;;-1:-1:-1;;;;;32892:46:10;;;;;;;;;;;;;;;32656:107;;-1:-1:-1;32892:71:10;;32656:107;;32892:5;;;;;:26;;:46;;;;;;;;;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;32892:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;32892:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;32892:46:10;;:71;:50;:71;:::i;:::-;33048:16;;;;:6;:16;;;;;:32;;;;33013:30;;;;;32873:90;;-1:-1:-1;32992:90:10;;33013:68;;;:34;:68;:::i;32992:90::-;33156:16;;;;:6;:16;;;;;:32;;;32973:109;;-1:-1:-1;33111:79:10;;33132:57;;:19;;:57;:23;:57;:::i;:::-;33111:16;;:79;:20;:79;:::i;:::-;33362:5;;:39;;;-1:-1:-1;;;33362:39:10;;-1:-1:-1;;;;;33362:39:10;;;;;;;;;;;;;;;33092:98;;-1:-1:-1;33313:89:10;;33362:5;;;;;:19;;:39;;;;;;;;;;;;;;:5;:39;;;5:2:-1;;;;30:1;27;20:12;5:2;33362:39:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;33362:39:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;33362:39:10;33313:5;;:44;;;-1:-1:-1;;;33313:44:10;;-1:-1:-1;;;;;33313:44:10;;;;;;;;;;;;;;;:5;;;;;:24;;:44;;;;;33362:39;;33313:44;;;;;;;:5;:44;;;5:2:-1;;;;30:1;27;20:12;33313:89:10;33482:16;;;;:6;:16;;;;;:32;;;;33448:29;;;;;33296:106;;-1:-1:-1;33429:87:10;;33448:67;;;:33;:67;:::i;:::-;33429:14;;:87;:18;:87;:::i;:::-;33586:16;;;;:6;:16;;;;;:32;;;33412:104;;-1:-1:-1;33543:77:10;;33562:57;;:19;;:57;:23;:57;:::i;:::-;33543:14;;:77;:18;:77;:::i;:::-;33818:16;;;;:6;:16;;;;;:30;;;;33783:29;;;;33746:32;;;;;33526:94;;-1:-1:-1;33662:212:10;;33746:118;;985:5;;33746:103;;33818:30;;33746:67;;:32;:67;:36;:67;:::i;:::-;:71;:103;:71;:103;:::i;:118::-;33699:16;;;;:6;:16;;;;;:28;;;;33662:32;;;;;:66;;;:36;:66;:::i;:212::-;33631:16;;;;:6;:16;;;;;:28;;;:243;;;;33884:26;;;:30;33981:32;;;33957:57;;:19;;:57;:23;:57;:::i;:::-;33924:16;;;;:6;:16;;;;;;;;;:30;;:90;;;;34058:5;;:40;;-1:-1:-1;;;34058:40:10;;-1:-1:-1;;;;;34058:40:10;;;;;;;;;;;;;;;:5;;;;;:20;;:40;;;;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;34058:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;34058:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;34058:40:10;34024:16;;;;:6;34058:40;34024:16;;;;:31;;;:74;;;;34145:28;;;;34108:34;;;:65;34183:35;;;:52;;;34245:37;;:56;;;34312:28;34031:8;34312:18;:28::i;:::-;31499:2848;;;;;;;:::o;34632:1390::-;34687:15;34705:16;;;:6;:16;;;;;;;;:23;;;34758:25;;;;34863:32;;;;;34819:5;;:39;;-1:-1:-1;;;34819:39:10;;-1:-1:-1;;;;;34705:23:10;;;34819:39;;;;;;;;;;;;;;34705:23;;34758:25;;34687:15;;34819:77;;34863:32;;34819:5;;;;:19;;:39;;;;;;;;;;:5;:39;;;5:2:-1;;;;30:1;27;20:12;34819:77:10;34793:103;;34906:18;34927:28;34946:8;34927:18;:28::i;:::-;35103:5;;:39;;;-1:-1:-1;;;35103:39:10;;-1:-1:-1;;;;;35103:39:10;;;;;;;;;;;;;;;34906:49;;-1:-1:-1;34965:21:10;;;;;;35103:5;;:19;;:39;;;;;;;;;;;;;;:5;:39;;;5:2:-1;;;;30:1;27;20:12;5:2;35103:39:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;35103:39:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;35103:39:10;35067:16;;;;:6;35103:39;35067:16;;;;:32;;;:75;35063:493;;;-1:-1:-1;35174:1:10;;-1:-1:-1;35174:1:10;;-1:-1:-1;985:5:10;35063:493;;;35296:5;;:43;;;-1:-1:-1;;;35296:43:10;;-1:-1:-1;;;;;35296:43:10;;;;;;;;;;;;;;;:5;;;;;:23;;:43;;;;;;;;;;;;;;:5;:43;;;5:2:-1;;;;30:1;27;20:12;5:2;35296:43:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;35296:43:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;35296:43:10;35367:5;;:44;;;-1:-1:-1;;;35367:44:10;;-1:-1:-1;;;;;35367:44:10;;;;;;;;;;;;;;;35296:43;;-1:-1:-1;35367:5:10;;;:24;;:44;;;;;35296:43;;35367:44;;;;;;;;:5;:44;;;5:2:-1;;;;30:1;27;20:12;5:2;35367:44:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;35367:44:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;35367:44:10;35441:5;;:46;;;-1:-1:-1;;;35441:46:10;;-1:-1:-1;;;;;35441:46:10;;;;;;;;;;;;;;;35367:44;;-1:-1:-1;35441:5:10;;;:26;;:46;;;;;35367:44;;35441:46;;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;35441:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;35441:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;35441:46:10;;-1:-1:-1;35501:44:10;35536:8;35501:34;:44::i;:::-;35597:1;35566:16;;;:6;:16;;;;;;;;:28;;;:32;;;;35608:26;;;:39;;;35657:30;;;;:47;;;35748:5;;:40;;-1:-1:-1;;;35748:40:10;;-1:-1:-1;;;;;35748:40:10;;;;;;;;;;;;;;;:5;;;;;:20;;:40;;;;;35566:16;;35748:40;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;35748:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;35748:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;35748:40:10;35714:16;;;;:6;35748:40;35714:16;;;;:31;;;:74;;;;35798:34;;;:50;;;35858:35;;;:52;;;35920:37;;:56;;;35987:28;35721:8;35987:18;:28::i;40082:2886::-;40137:15;40155:16;;;:6;:16;;;;;;;;:23;;;40208:25;;;;40659:5;;:46;;-1:-1:-1;;;40659:46:10;;-1:-1:-1;;;;;40155:23:10;;;40659:46;;;;;;;;;;;;;;40155:23;;40208:25;;40137:15;;;;;;40659:5;;;;:26;;:46;;;;;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;40659:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;40659:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;40659:46:10;;-1:-1:-1;985:5:10;40719:30;;40715:91;;;-1:-1:-1;985:5:10;40715:91;40836:33;:18;985:5;40836:33;:22;:33;:::i;:::-;40972:16;;;;:6;:16;;;;;;;;;:28;;;40923:5;;:43;;-1:-1:-1;;;40923:43:10;;-1:-1:-1;;;;;40923:43:10;;;;;;;;;;;;;;;40815:54;;-1:-1:-1;40900:101:10;;40972:28;;40900:67;;40923:5;;;:23;;:43;;;;;40972:16;;40923:43;;;;;;:5;:43;;;5:2:-1;;;;30:1;27;20:12;40900:101:10;41015:5;;:46;;;-1:-1:-1;;;41015:46:10;;-1:-1:-1;;;;;41015:46:10;;;;;;;;;;;;;;;40879:122;;-1:-1:-1;40879:122:10;;41015:5;;;;;:26;;:46;;;;;;;;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;41015:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;41015:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;41015:46:10;:67;41011:242;;;41142:5;;:46;;;-1:-1:-1;;;41142:46:10;;-1:-1:-1;;;;;41142:46:10;;;;;;;;;;;;;;;41119:70;;41142:5;;;;;:26;;:46;;;;;;;;;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;41142:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;41142:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;41142:46:10;41119:18;;:70;:22;:70;:::i;:::-;41098:91;;41011:242;;;-1:-1:-1;41241:1:10;41011:242;41317:5;;:40;;;-1:-1:-1;;;41317:40:10;;-1:-1:-1;;;;;41317:40:10;;;;;;;;;;;;;;;41263:28;;41294:79;;985:5;;41294:64;;41317:5;;;;;:20;;:40;;;;;;;;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;41294:79:10;41502:5;;:46;;;-1:-1:-1;;;41502:46:10;;-1:-1:-1;;;;;41502:46:10;;;;;;;;;;;;;;;41263:110;;-1:-1:-1;41502:72:10;;41263:110;;41502:5;;;;;:26;;:46;;;;;;;;;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;41502:72:10;41659:16;;;;:6;:16;;;;;:33;;;;41624:30;;;;;41483:91;;-1:-1:-1;41603:91:10;;41624:69;;;:34;:69;:::i;41603:91::-;41769:16;;;;:6;:16;;;;;:33;;;41584:110;;-1:-1:-1;41723:81:10;;41744:59;;:20;;:59;:24;:59;:::i;41723:81::-;41976:5;;:40;;;-1:-1:-1;;;41976:40:10;;-1:-1:-1;;;;;41976:40:10;;;;;;;;;;;;;;;41704:100;;-1:-1:-1;41927:90:10;;41976:5;;;;;:20;;:40;;;;;;;;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;41927:90:10;42097:16;;;;:6;:16;;;;;:33;;;;42063:29;;;;;41910:107;;-1:-1:-1;42044:88:10;;42063:68;;;:33;:68;:::i;42044:88::-;42203:16;;;;:6;:16;;;;;:33;;;42027:105;;-1:-1:-1;42159:79:10;;42178:59;;:20;;:59;:24;:59;:::i;42159:79::-;42438:16;;;;:6;:16;;;;;:30;;;;42403:29;;;;42365:33;;;;;42142:96;;-1:-1:-1;42280:214:10;;42365:119;;985:5;;42365:104;;42438:30;;42365:68;;:33;:68;:37;:68;:::i;:119::-;42318:16;;;;:6;:16;;;;;:28;;;;42280:33;;;;;:67;;;:37;:67;:::i;:214::-;42249:16;;;;:6;:16;;;;;;;;:28;;;:245;;;;42504:26;;;;:30;;;;42577:5;;:39;;-1:-1:-1;;;42577:39:10;;-1:-1:-1;;;;;42577:39:10;;;;;;;;;;;;;;;:5;;;;;:19;;:39;;;;;42249:16;;42577:39;;;;;;:5;:39;;;5:2:-1;;;;30:1;27;20:12;5:2;42577:39:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;42577:39:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;42577:39:10;42544:16;;;;:6;42577:39;42544:16;;;;:30;;;:72;;;;42685:33;;;42660:59;;:20;;:59;:24;:59;:::i;:::-;42626:16;;;;:6;:16;;;;;:31;;;:93;;;;42766:28;;;;42729:34;;;:65;42804:35;;;:52;;;42866:37;;:56;;;42933:28;42633:8;42933:18;:28::i;3718:338:12:-;3804:7;3904:12;3897:5;3889:28;;;;-1:-1:-1;;;3889:28:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3927:9;3943:1;3939;:5;;;;;;;3718:338;-1:-1:-1;;;;;3718:338:12:o;1732:187::-;1818:7;1853:12;1845:6;;;;1837:29;;;;-1:-1:-1;;;1837:29:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;1837:29:12;-1:-1:-1;;;1888:5:12;;;1732:187::o;36754:1401:10:-;36822:18;36870:16;;;:6;:16;;;;;:23;;;36923:25;;;36992:31;;;;;-1:-1:-1;;;;;36870:23:10;;;;36923:25;36822:18;;36992:31;;36988:1116;;37094:16;;;;:6;:16;;;;;;;;;:32;;;37186:5;;:43;;-1:-1:-1;;;37186:43:10;;-1:-1:-1;;;;;37186:43:10;;;;;;;;;;;;;;;37094:32;;-1:-1:-1;37154:390:10;;37186:5;;;;:23;;:43;;;;;;;;;;:5;:43;;;5:2:-1;;;;30:1;27;20:12;5:2;37186:43:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;37186:43:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;37186:43:10;37247:5;;:46;;;-1:-1:-1;;;37247:46:10;;-1:-1:-1;;;;;37247:46:10;;;;;;;;;;;;;;;:5;;;;;:26;;:46;;;;;37186:43;;37247:46;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;37247:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;37247:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;37247:46:10;37311:5;;:40;;;-1:-1:-1;;;37311:40:10;;-1:-1:-1;;;;;37311:40:10;;;;;;;;;;;;;;;:5;;;;;:20;;:40;;;;;37247:46;;37311:40;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;37311:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;37311:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;37311:40:10;37369:16;;;;:6;37311:40;37369:16;;;;;;;;:28;;;;37415:29;;;;;37462:5;;:46;;-1:-1:-1;;;37462:46:10;;-1:-1:-1;;;;;37462:46:10;;;;;;;;;;;;;;;37369:28;;37415:29;;37462:5;;;;;:26;;:46;;;;;37311:40;;37462:46;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;37462:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;37462:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;37462:46:10;37526:4;37154:14;:390::i;:::-;37140:404;;36988:1116;;;37641:16;;;;:6;:16;;;;;;;;;:33;;;37735:5;;:43;;-1:-1:-1;;;37735:43:10;;-1:-1:-1;;;;;37735:43:10;;;;;;;;;;;;;;;37641:33;;-1:-1:-1;37702:391:10;;37735:5;;;;:23;;:43;;;;;;;;;;:5;:43;;;5:2:-1;;;;30:1;27;20:12;5:2;37735:43:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;37735:43:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;37735:43:10;37796:5;;:46;;;-1:-1:-1;;;37796:46:10;;-1:-1:-1;;;;;37796:46:10;;;;;;;;;;;;;;;:5;;;;;:26;;:46;;;;;37735:43;;37796:46;;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;37796:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;37796:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;37796:46:10;37860:5;;:40;;;-1:-1:-1;;;37860:40:10;;-1:-1:-1;;;;;37860:40:10;;;;;;;;;;;;;;;:5;;;;;:20;;:40;;;;;37796:46;;37860:40;;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;37860:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;37860:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;37860:40:10;37918:16;;;;:6;37860:40;37918:16;;;;;;;;:28;;;;37964:29;;;;;38011:5;;:46;;-1:-1:-1;;;38011:46:10;;-1:-1:-1;;;;;38011:46:10;;;;;;;;;;;;;;;37918:28;;37964:29;;38011:5;;;;;:26;;:46;;;;;37860:40;;38011:46;;;;;;:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;38011:46:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;38011:46:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;38011:46:10;38075:4;37702:15;:391::i;:::-;37688:405;;36988:1116;38120:27;:10;38135:11;38120:27;:14;:27;:::i;36109:362::-;36186:14;36203:16;;;:6;:16;;;;;;;;:23;;;36251:25;;;;36301:5;;:38;;-1:-1:-1;;;36301:38:10;;-1:-1:-1;;;;;36203:23:10;;;36301:38;;;;;;;;;;;;;;36203:23;;36251:25;;36186:14;;36301:5;;;;;:20;;:38;;;;;;;;;;:5;:38;;;5:2:-1;;;;30:1;27;20:12;5:2;36301:38:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;36301:38:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;36301:38:10;36382:16;;;;:6;36301:38;36382:16;;;;;;;;:26;;;;36350:72;;;;;;;;;;;;;;;;;36301:38;;-1:-1:-1;36350:72:10;;;;;;;;;;36428:16;;;;:6;:16;;;;;;;;:26;;;:40;;;;-1:-1:-1;;36109:362:10:o;44781:1893::-;44929:16;;;;:6;:16;;;;;;;;;:28;;;;44898:26;;;;44853:5;;44869:23;;44853:40;;-1:-1:-1;;;44853:40:10;;-1:-1:-1;;;;;44869:23:10;;;44853:40;;;;;;44929:28;;44853:72;;44898:26;;44853:5;;;;;:15;;:40;;;;;44929:16;;44853:40;;;;;;:5;:40;;;5:2:-1;;;;30:1;27;20:12;5:2;44853:40:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;44853:40:10;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;44853:40:10;;:72;:44;:72;:::i;:::-;:104;;44845:156;;;;-1:-1:-1;;;44845:156:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45011:33;45035:8;45011:23;:33::i;:::-;-1:-1:-1;45128:16:10;;;;:6;:16;;;;;:28;;;;45099:26;;;;;:57;45095:329;;;45203:16;;;;:6;:16;;;;;:28;;;;45172:26;;;;;:60;;;:30;:60;:::i;:::-;-1:-1:-1;45277:1:10;45246:16;;;:6;:16;;;;;:28;;:32;45095:329;;;45342:16;;;;:6;:16;;;;;:26;;;;45309:28;;;;;:60;;;:32;:60;:::i;:::-;-1:-1:-1;45412:1:10;45383:16;;;:6;:16;;;;;:26;;:30;45095:329;45466:1;45437:16;;;:6;:16;;;;;:26;;;:30;45433:133;;45483:14;;;45503:16;;;:6;:16;;;;;;:23;;45528:26;;;;;45483:72;;-1:-1:-1;;;45483:72:10;;-1:-1:-1;;;;;45503:23:10;;;45483:72;;;;;;;;;;;;;:14;;;:19;;:72;;;;;:14;;:72;;;;;;:14;;:72;;;5:2:-1;;;;30:1;27;20:12;5:2;45483:72:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;45483:72:10;;;;45433:133;45610:1;45579:16;;;:6;:16;;;;;:28;;;:32;45575:128;;45627:5;;;45638:16;;;:6;:16;;;;;;:23;;45663:28;;;;;45627:65;;-1:-1:-1;;;45627:65:10;;-1:-1:-1;;;;;45638:23:10;;;45627:65;;;;;;;;;;;;;:5;;;:10;;:65;;;;;:5;;:65;;;;;;:5;;:65;;;5:2:-1;;;;30:1;27;20:12;5:2;45627:65:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;45627:65:10;;;;45575:128;45712:5;;;;45743:16;;;:6;:16;;;;;;;;:23;;45780:25;;;;45819:26;;;;45859:30;;;;45903:31;;;;45948:34;;;;45996:35;;;;46045:37;;;;46096:36;;;;;45712:430;;-1:-1:-1;;;45712:430:10;;-1:-1:-1;;;;;45743:23:10;;;45712:430;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:5;;;;;:17;;:430;;;;;:5;:430;;;;;;:5;;:430;;;5:2:-1;;;;30:1;27;20:12;5:2;45712:430:10;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;46186:16:10;;;;:6;:16;;;;;;;;;:23;;;46223:25;;;46262:26;;;;46302:30;;;;46346:31;;;;46391:34;;;;46439:35;;;;46488:37;;;;46539:36;;;;46589:26;;;;46629:28;;;;;46157:510;;-1:-1:-1;;;;;46186:23:10;;;46157:510;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46186:23;46157:510;;;;;;;;;;;;;;;;;;-1:-1:-1;46157:510:10;;;;;;;;44781:1893;:::o

Swarm Source

bzzr://cb9a00bd74f3aa4fa52897b6a4e7577ae149655caffe63aac6692578ab03023a

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

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