ETH Price: $2,858.56 (-2.81%)

Contract

0x5220Ffb7307a67d41062A261feF5136516637F65

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To
Execute Nft Orde...980729302023-06-05 15:02:41965 days ago1685977361IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000192820.1
Execute Nft Orde...980700032023-06-05 14:50:25965 days ago1685976625IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000131510.1
Execute Nft Orde...980668832023-06-05 14:37:22965 days ago1685975842IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000134770.1
Execute Nft Orde...980652162023-06-05 14:30:24965 days ago1685975424IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000126830.1
Execute Nft Orde...980640862023-06-05 14:25:42965 days ago1685975142IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000129790.1
Execute Nft Orde...980614542023-06-05 14:14:43965 days ago1685974483IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000123980.1
Execute Nft Orde...980614092023-06-05 14:14:32965 days ago1685974472IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000125130.1
Execute Nft Orde...980613672023-06-05 14:14:21965 days ago1685974461IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000122840.1
Execute Nft Orde...980613242023-06-05 14:14:11965 days ago1685974451IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000121690.1
Execute Nft Orde...980612752023-06-05 14:13:58965 days ago1685974438IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000125890.1
Execute Nft Orde...980612322023-06-05 14:13:47965 days ago1685974427IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000125890.1
Execute Nft Orde...980611902023-06-05 14:13:37965 days ago1685974417IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000124750.1
Execute Nft Orde...980611412023-06-05 14:13:24965 days ago1685974404IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000122070.1
Execute Nft Orde...980610762023-06-05 14:13:08965 days ago1685974388IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000126270.1
Execute Nft Orde...980609842023-06-05 14:12:48965 days ago1685974368IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000123350.1
Execute Nft Orde...980609052023-06-05 14:12:28965 days ago1685974348IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000122980.1
Execute Nft Orde...980608332023-06-05 14:12:10965 days ago1685974330IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000120370.1
Execute Nft Orde...980608222023-06-05 14:12:07965 days ago1685974327IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000121120.1
Execute Nft Orde...980606982023-06-05 14:11:36965 days ago1685974296IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000122240.1
Execute Nft Orde...980606982023-06-05 14:11:36965 days ago1685974296IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000120750.1
Execute Nft Orde...980601892023-06-05 14:09:28965 days ago1685974168IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000122240.1
Execute Nft Orde...980601892023-06-05 14:09:28965 days ago1685974168IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000121490.1
Execute Nft Orde...980601032023-06-05 14:09:06965 days ago1685974146IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000125590.1
Execute Nft Orde...980600602023-06-05 14:08:55965 days ago1685974135IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000123350.1
Execute Nft Orde...980600172023-06-05 14:08:44965 days ago1685974124IN
Gains Network: GNS Trading V6.3.1 (Legacy)
0 ETH0.000123350.1
View all transactions

Parent Transaction Hash Block From To
View All Internal Transactions

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
GNSTradingV6_3_1

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 275 runs

Other Settings:
default evmVersion
// SPDX-License-Identifier: MIT
import '../interfaces/StorageInterfaceV5.sol';
import '../interfaces/GNSPairInfosInterfaceV6.sol';
import '../interfaces/GNSReferralsInterfaceV6_2.sol';
import '../v6.2/Delegatable.sol';
import '../libraries/ChainUtils.sol';
import '../libraries/TradeUtils.sol';

pragma solidity 0.8.17;

contract GNSTradingV6_3_1 is Delegatable {
    using TradeUtils for address;

    // Contracts (constant)
    StorageInterfaceV5 public immutable storageT;
    NftRewardsInterfaceV6_3_1 public immutable nftRewards;
    GNSPairInfosInterfaceV6 public immutable pairInfos;
    GNSReferralsInterfaceV6_2 public immutable referrals;

    // Params (constant)
    uint constant PRECISION = 1e10;
    uint constant MAX_SL_P = 75;  // -75% PNL

    // Params (adjustable)
    uint public maxPosDai;            // 1e18 (eg. 75000 * 1e18)
    uint public marketOrdersTimeout;  // block (eg. 30)

    // State
    bool public isPaused;  // Prevent opening new trades
    bool public isDone;    // Prevent any interaction with the contract

    // Events
    event Done(bool done);
    event Paused(bool paused);

    event NumberUpdated(string name, uint value);

    event MarketOrderInitiated(
        uint indexed orderId,
        address indexed trader,
        uint indexed pairIndex,
        bool open
    );

    event OpenLimitPlaced(
        address indexed trader,
        uint indexed pairIndex,
        uint index
    );
    event OpenLimitUpdated(
        address indexed trader,
        uint indexed pairIndex,
        uint index,
        uint newPrice,
        uint newTp,
        uint newSl
    );
    event OpenLimitCanceled(
        address indexed trader,
        uint indexed pairIndex,
        uint index
    );

    event TpUpdated(
        address indexed trader,
        uint indexed pairIndex,
        uint index,
        uint newTp
    );
    event SlUpdated(
        address indexed trader,
        uint indexed pairIndex,
        uint index,
        uint newSl
    );
    event SlUpdateInitiated(
        uint indexed orderId,
        address indexed trader,
        uint indexed pairIndex,
        uint index,
        uint newSl
    );

    event NftOrderInitiated(
        uint orderId,
        address indexed nftHolder,
        address indexed trader,
        uint indexed pairIndex
    );
    event NftOrderSameBlock(
        address indexed nftHolder,
        address indexed trader,
        uint indexed pairIndex
    );

    event ChainlinkCallbackTimeout(
        uint indexed orderId,
        StorageInterfaceV5.PendingMarketOrder order
    );
    event CouldNotCloseTrade(
        address indexed trader,
        uint indexed pairIndex,
        uint index
    );

    constructor(
        StorageInterfaceV5 _storageT,
        NftRewardsInterfaceV6_3_1 _nftRewards,
        GNSPairInfosInterfaceV6 _pairInfos,
        GNSReferralsInterfaceV6_2 _referrals,
        uint _maxPosDai,
        uint _marketOrdersTimeout
    ) {
        require(address(_storageT) != address(0)
            && address(_nftRewards) != address(0)
            && address(_pairInfos) != address(0)
            && address(_referrals) != address(0)
            && _maxPosDai > 0
            && _marketOrdersTimeout > 0, "WRONG_PARAMS");

        storageT = _storageT;
        nftRewards = _nftRewards;
        pairInfos = _pairInfos;
        referrals = _referrals;

        maxPosDai = _maxPosDai;
        marketOrdersTimeout = _marketOrdersTimeout;
    }

    // Modifiers
    modifier onlyGov(){
        isGov();
        _;
    }
    modifier notContract(){
        isNotContract();
        _;
    }
    modifier notDone(){
        isNotDone();
        _;
    }

    // Saving code size by calling these functions inside modifiers
    function isGov() private view {
        require(msg.sender == storageT.gov(), "GOV_ONLY");
    }
    function isNotContract() private view {
        require(tx.origin == msg.sender);
    }
    function isNotDone() private view {
        require(!isDone, "DONE");
    }

    // Manage params
    function setMaxPosDai(uint value) external onlyGov{
        require(value > 0, "VALUE_0");
        maxPosDai = value;

        emit NumberUpdated("maxPosDai", value);
    }
    function setMarketOrdersTimeout(uint value) external onlyGov{
        require(value > 0, "VALUE_0");
        marketOrdersTimeout = value;

        emit NumberUpdated("marketOrdersTimeout", value);
    }

    // Manage state
    function pause() external onlyGov{
        isPaused = !isPaused;

        emit Paused(isPaused);
    }
    function done() external onlyGov{
        isDone = !isDone;

        emit Done(isDone);
    }

    // Open new trade (MARKET/LIMIT)
    function openTrade(
        StorageInterfaceV5.Trade memory t,
        NftRewardsInterfaceV6_3_1.OpenLimitOrderType orderType, // LEGACY => market
        uint spreadReductionId,
        uint slippageP, // for market orders only
        address referrer
    ) external notContract notDone {

        require(!isPaused, "PAUSED");
        require(t.openPrice * slippageP < type(uint256).max, "OVERFLOW");

        AggregatorInterfaceV6_2 aggregator = storageT.priceAggregator();
        PairsStorageInterfaceV6 pairsStored = aggregator.pairsStorage();

        address sender = _msgSender();

        require(storageT.openTradesCount(sender, t.pairIndex)
            + storageT.pendingMarketOpenCount(sender, t.pairIndex)
            + storageT.openLimitOrdersCount(sender, t.pairIndex)
            < storageT.maxTradesPerPair(),
            "MAX_TRADES_PER_PAIR");

        require(storageT.pendingOrderIdsCount(sender)
            < storageT.maxPendingMarketOrders(),
            "MAX_PENDING_ORDERS");

        require(t.positionSizeDai <= maxPosDai, "ABOVE_MAX_POS");
        require(t.positionSizeDai * t.leverage
            >= pairsStored.pairMinLevPosDai(t.pairIndex), "BELOW_MIN_POS");

        require(t.leverage > 0 && t.leverage >= pairsStored.pairMinLeverage(t.pairIndex)
            && t.leverage <= pairsStored.pairMaxLeverage(t.pairIndex),
            "LEVERAGE_INCORRECT");

        require(spreadReductionId == 0
            || storageT.nfts(spreadReductionId - 1).balanceOf(sender) > 0,
            "NO_CORRESPONDING_NFT_SPREAD_REDUCTION");

        require(t.tp == 0 || (t.buy ?
                t.tp > t.openPrice :
                t.tp < t.openPrice), "WRONG_TP");

        require(t.sl == 0 || (t.buy ?
                t.sl < t.openPrice :
                t.sl > t.openPrice), "WRONG_SL");

        (uint priceImpactP, ) = pairInfos.getTradePriceImpact(
            0,
            t.pairIndex,
            t.buy,
            t.positionSizeDai * t.leverage
        );

        require(priceImpactP * t.leverage
            <= pairInfos.maxNegativePnlOnOpenP(), "PRICE_IMPACT_TOO_HIGH");

        storageT.transferDai(sender, address(storageT), t.positionSizeDai);

        if(orderType != NftRewardsInterfaceV6_3_1.OpenLimitOrderType.LEGACY){
            uint index = storageT.firstEmptyOpenLimitIndex(sender, t.pairIndex);

            storageT.storeOpenLimitOrder(
                StorageInterfaceV5.OpenLimitOrder(
                    sender,
                    t.pairIndex,
                    index,
                    t.positionSizeDai,
                    spreadReductionId > 0 ?
                        storageT.spreadReductionsP(spreadReductionId - 1) :
                        0,
                    t.buy,
                    t.leverage,
                    t.tp,
                    t.sl,
                    t.openPrice,
                    t.openPrice,
                    block.number,
                    0
                )
            );

            nftRewards.setOpenLimitOrderType(sender, t.pairIndex, index, orderType);
            storageT.callbacks().setTradeLastUpdated(
                sender,
                t.pairIndex,
                index,
                TradingCallbacksV6_3_1.TradeType.LIMIT,
                ChainUtils.getBlockNumber()
            );

            emit OpenLimitPlaced(
                sender,
                t.pairIndex,
                index
            );

        }else{
            uint orderId = aggregator.getPrice(
                t.pairIndex,
                AggregatorInterfaceV6_2.OrderType.MARKET_OPEN,
                t.positionSizeDai * t.leverage
            );

            storageT.storePendingMarketOrder(
                StorageInterfaceV5.PendingMarketOrder(
                    StorageInterfaceV5.Trade(
                        sender,
                        t.pairIndex,
                        0,
                        0,
                        t.positionSizeDai,
                        0,
                        t.buy,
                        t.leverage,
                        t.tp,
                        t.sl
                    ),
                    0,
                    t.openPrice,
                    slippageP,
                    spreadReductionId > 0 ?
                        storageT.spreadReductionsP(spreadReductionId - 1) :
                        0,
                    0
                ), orderId, true
            );

            emit MarketOrderInitiated(
                orderId,
                sender,
                t.pairIndex,
                true
            );
        }

        referrals.registerPotentialReferrer(sender, referrer);
    }

    // Close trade (MARKET)
    function closeTradeMarket(
        uint pairIndex,
        uint index
    ) external notContract notDone {

        address sender = _msgSender();

        StorageInterfaceV5.Trade memory t = storageT.openTrades(
            sender, pairIndex, index
        );

        StorageInterfaceV5.TradeInfo memory i = storageT.openTradesInfo(
            sender, pairIndex, index
        );

        require(storageT.pendingOrderIdsCount(sender)
            < storageT.maxPendingMarketOrders(), "MAX_PENDING_ORDERS");

        require(!i.beingMarketClosed, "ALREADY_BEING_CLOSED");
        require(t.leverage > 0, "NO_TRADE");

        uint orderId = storageT.priceAggregator().getPrice(
            pairIndex,
            AggregatorInterfaceV6_2.OrderType.MARKET_CLOSE,
            t.initialPosToken * i.tokenPriceDai * t.leverage / PRECISION
        );

        storageT.storePendingMarketOrder(
            StorageInterfaceV5.PendingMarketOrder(
                StorageInterfaceV5.Trade(
                    sender, pairIndex, index, 0, 0, 0, false, 0, 0, 0
                ),
                0, 0, 0, 0, 0
            ), orderId, false
        );

        emit MarketOrderInitiated(
            orderId,
            sender,
            pairIndex,
            false
        );
    }

    // Manage limit order (OPEN)
    function updateOpenLimitOrder(
        uint pairIndex,
        uint index,
        uint price,  // PRECISION
        uint tp,
        uint sl
    ) external notContract notDone {

        address sender = _msgSender();

        require(storageT.hasOpenLimitOrder(sender, pairIndex, index),
            "NO_LIMIT");

        StorageInterfaceV5.OpenLimitOrder memory o = storageT.getOpenLimitOrder(
            sender, pairIndex, index
        );

        require(tp == 0 || (o.buy ?
            tp > price :
            tp < price), "WRONG_TP");

        require(sl == 0 || (o.buy ?
            sl < price :
            sl > price), "WRONG_SL");

        checkNoPendingTrigger(sender, pairIndex, index, StorageInterfaceV5.LimitOrder.OPEN);

        o.minPrice = price;
        o.maxPrice = price;
        o.tp = tp;
        o.sl = sl;

        storageT.updateOpenLimitOrder(o);
        storageT.callbacks().setTradeLastUpdated(
            sender,
            pairIndex,
            index,
            TradingCallbacksV6_3_1.TradeType.LIMIT,
            ChainUtils.getBlockNumber()
        );

        emit OpenLimitUpdated(
            sender,
            pairIndex,
            index,
            price,
            tp,
            sl
        );
    }

    function cancelOpenLimitOrder(
        uint pairIndex,
        uint index
    ) external notContract notDone {

        address sender = _msgSender();

        require(storageT.hasOpenLimitOrder(sender, pairIndex, index),
            "NO_LIMIT");

        StorageInterfaceV5.OpenLimitOrder memory o = storageT.getOpenLimitOrder(
            sender, pairIndex, index
        );

        checkNoPendingTrigger(sender, pairIndex, index, StorageInterfaceV5.LimitOrder.OPEN);

        storageT.unregisterOpenLimitOrder(sender, pairIndex, index);
        storageT.transferDai(address(storageT), sender, o.positionSize);

        emit OpenLimitCanceled(
            sender,
            pairIndex,
            index
        );
    }

    // Manage limit order (TP/SL)
    function updateTp(
        uint pairIndex,
        uint index,
        uint newTp
    ) external notContract notDone {

        address sender = _msgSender();

        checkNoPendingTrigger(sender, pairIndex, index, StorageInterfaceV5.LimitOrder.TP);

        StorageInterfaceV5.Trade memory t = storageT.openTrades(
            sender, pairIndex, index
        );

        require(t.leverage > 0, "NO_TRADE");

        storageT.updateTp(sender, pairIndex, index, newTp);
        storageT.callbacks().setTpLastUpdated(
            sender,
            pairIndex,
            index,
            TradingCallbacksV6_3_1.TradeType.MARKET,
            ChainUtils.getBlockNumber()
        );

        emit TpUpdated(
            sender,
            pairIndex,
            index,
            newTp
        );
    }

    function updateSl(
        uint pairIndex,
        uint index,
        uint newSl
    ) external notContract notDone {

        address sender = _msgSender();

        checkNoPendingTrigger(sender, pairIndex, index, StorageInterfaceV5.LimitOrder.SL);

        StorageInterfaceV5.Trade memory t = storageT.openTrades(
            sender, pairIndex, index
        );

        StorageInterfaceV5.TradeInfo memory i = storageT.openTradesInfo(
            sender, pairIndex, index
        );

        require(t.leverage > 0, "NO_TRADE");

        uint maxSlDist = t.openPrice * MAX_SL_P / 100 / t.leverage;

        require(newSl == 0 || (t.buy ?
            newSl >= t.openPrice - maxSlDist :
            newSl <= t.openPrice + maxSlDist), "SL_TOO_BIG");

        AggregatorInterfaceV6_2 aggregator = storageT.priceAggregator();

        if(newSl == 0
        || !aggregator.pairsStorage().guaranteedSlEnabled(pairIndex)){

            storageT.updateSl(sender, pairIndex, index, newSl);
            storageT.callbacks().setSlLastUpdated(
                sender,
                pairIndex,
                index,
                TradingCallbacksV6_3_1.TradeType.MARKET,
                ChainUtils.getBlockNumber()
            );

            emit SlUpdated(
                sender,
                pairIndex,
                index,
                newSl
            );

        }else{
            uint orderId = aggregator.getPrice(
                pairIndex,
                AggregatorInterfaceV6_2.OrderType.UPDATE_SL,
                t.initialPosToken * i.tokenPriceDai * t.leverage / PRECISION
            );

            aggregator.storePendingSlOrder(
                orderId,
                AggregatorInterfaceV6_2.PendingSl(
                    sender, pairIndex, index, t.openPrice, t.buy, newSl
                )
            );

            emit SlUpdateInitiated(
                orderId,
                sender,
                pairIndex,
                index,
                newSl
            );
        }
    }

    // Execute limit order
    function executeNftOrder(
        StorageInterfaceV5.LimitOrder orderType,
        address trader,
        uint pairIndex,
        uint index,
        uint nftId,
        uint nftType
    ) external notContract notDone {

        address sender = _msgSender();

        require(nftType >= 1 && nftType <= 5, "WRONG_NFT_TYPE");
        require(storageT.nfts(nftType - 1).ownerOf(nftId) == sender, "NO_NFT");

        require(block.number >=
            storageT.nftLastSuccess(nftId) + storageT.nftSuccessTimelock(),
            "SUCCESS_TIMELOCK");
        require(
            canExecute(
                orderType,
                TradingCallbacksV6_3_1.SimplifiedTradeId(
                    trader,
                    pairIndex,
                    index,
                    orderType == StorageInterfaceV5.LimitOrder.OPEN
                        ? TradingCallbacksV6_3_1.TradeType.LIMIT
                        : TradingCallbacksV6_3_1.TradeType.MARKET
                )
            ),
            "IN_TIMEOUT"
        );

        {
            (bytes32 nftHash, bytes32 botHash) = nftRewards.getNftBotHashes(
                block.number,
                sender,
                nftId,
                trader,
                pairIndex,
                index
            );
            require(!nftRewards.nftBotInUse(nftHash, botHash), "BOT_IN_USE");

            nftRewards.setNftBotInUse(nftHash, botHash);
        }

        StorageInterfaceV5.Trade memory t;

        if(orderType == StorageInterfaceV5.LimitOrder.OPEN){
            require(storageT.hasOpenLimitOrder(trader, pairIndex, index),
                "NO_LIMIT");

        }else{
            t = storageT.openTrades(trader, pairIndex, index);

            require(t.leverage > 0, "NO_TRADE");

            if(orderType == StorageInterfaceV5.LimitOrder.LIQ){
                uint liqPrice = pairInfos.getTradeLiquidationPrice(
                    t.trader,
                    t.pairIndex,
                    t.index,
                    t.openPrice,
                    t.buy,
                    t.initialPosToken * storageT.openTradesInfo(
                        t.trader, t.pairIndex, t.index
                    ).tokenPriceDai / PRECISION,
                    t.leverage
                );

                require(t.sl == 0 || (t.buy ?
                    liqPrice > t.sl :
                    liqPrice < t.sl), "HAS_SL");

            }else{
                require(orderType != StorageInterfaceV5.LimitOrder.SL || t.sl > 0,
                    "NO_SL");
                require(orderType != StorageInterfaceV5.LimitOrder.TP || t.tp > 0,
                    "NO_TP");
            }
        }

        NftRewardsInterfaceV6_3_1.TriggeredLimitId memory triggeredLimitId =
            NftRewardsInterfaceV6_3_1.TriggeredLimitId(
                trader, pairIndex, index, orderType
            );

        if(!nftRewards.triggered(triggeredLimitId)
        || nftRewards.timedOut(triggeredLimitId)){

            uint leveragedPosDai;

            if(orderType == StorageInterfaceV5.LimitOrder.OPEN){

                StorageInterfaceV5.OpenLimitOrder memory l = storageT.getOpenLimitOrder(
                    trader, pairIndex, index
                );

                leveragedPosDai = l.positionSize * l.leverage;

                (uint priceImpactP, ) = pairInfos.getTradePriceImpact(
                    0,
                    l.pairIndex,
                    l.buy,
                    leveragedPosDai
                );

                require(priceImpactP * l.leverage <= pairInfos.maxNegativePnlOnOpenP(),
                    "PRICE_IMPACT_TOO_HIGH");

            }else{
                leveragedPosDai = t.initialPosToken * storageT.openTradesInfo(
                    trader, pairIndex, index
                ).tokenPriceDai * t.leverage / PRECISION;
            }

            storageT.transferLinkToAggregator(sender, pairIndex, leveragedPosDai);

            AggregatorInterfaceV6_2 aggregator = storageT.priceAggregator();
            uint orderId = aggregator.getPrice(
                pairIndex,
                orderType == StorageInterfaceV5.LimitOrder.OPEN ?
                    AggregatorInterfaceV6_2.OrderType.LIMIT_OPEN :
                    AggregatorInterfaceV6_2.OrderType.LIMIT_CLOSE,
                leveragedPosDai
            );

            storageT.storePendingNftOrder(
                StorageInterfaceV5.PendingNftOrder(
                    sender,
                    nftId,
                    trader,
                    pairIndex,
                    index,
                    orderType
                ), orderId
            );

            nftRewards.storeFirstToTrigger(triggeredLimitId, sender, aggregator.linkFee(pairIndex, leveragedPosDai));

            emit NftOrderInitiated(
                orderId,
                sender,
                trader,
                pairIndex
            );

        }else{
            nftRewards.storeTriggerSameBlock(triggeredLimitId, sender);

            emit NftOrderSameBlock(
                sender,
                trader,
                pairIndex
            );
        }
    }

    // Market timeout
    function openTradeMarketTimeout(uint _order) external notContract notDone {
        address sender = _msgSender();

        StorageInterfaceV5.PendingMarketOrder memory o =
            storageT.reqID_pendingMarketOrder(_order);

        StorageInterfaceV5.Trade memory t = o.trade;

        require(o.block > 0
            && block.number >= o.block + marketOrdersTimeout, "WAIT_TIMEOUT");

        require(t.trader == sender, "NOT_YOUR_ORDER");
        require(t.leverage > 0, "WRONG_MARKET_ORDER_TYPE");

        storageT.unregisterPendingMarketOrder(_order, true);
        storageT.transferDai(address(storageT), sender, t.positionSizeDai);

        emit ChainlinkCallbackTimeout(
            _order,
            o
        );
    }

    function closeTradeMarketTimeout(uint _order) external notContract notDone {
        address sender = _msgSender();

        StorageInterfaceV5.PendingMarketOrder memory o =
            storageT.reqID_pendingMarketOrder(_order);

        StorageInterfaceV5.Trade memory t = o.trade;

        require(o.block > 0
            && block.number >= o.block + marketOrdersTimeout, "WAIT_TIMEOUT");

        require(t.trader == sender, "NOT_YOUR_ORDER");
        require(t.leverage == 0, "WRONG_MARKET_ORDER_TYPE");

        storageT.unregisterPendingMarketOrder(_order, false);

        (bool success, ) = address(this).delegatecall(
            abi.encodeWithSignature(
                "closeTradeMarket(uint256,uint256)",
                t.pairIndex,
                t.index
            )
        );

        if(!success){
            emit CouldNotCloseTrade(
                sender,
                t.pairIndex,
                t.index
            );
        }

        emit ChainlinkCallbackTimeout(
            _order,
            o
        );
    }

    // Helpers
    function checkNoPendingTrigger(
        address trader,
        uint pairIndex,
        uint index,
        StorageInterfaceV5.LimitOrder orderType
    ) private view {
        NftRewardsInterfaceV6_3_1.TriggeredLimitId memory triggeredLimitId =
            NftRewardsInterfaceV6_3_1.TriggeredLimitId(
                trader, pairIndex, index, orderType
            );
        require(!nftRewards.triggered(triggeredLimitId)
            || nftRewards.timedOut(triggeredLimitId), "PENDING_TRIGGER");
    }

    function canExecute(
        StorageInterfaceV5.LimitOrder orderType,
        TradingCallbacksV6_3_1.SimplifiedTradeId memory id
    ) private view returns(bool) {
        if (orderType == StorageInterfaceV5.LimitOrder.LIQ)
            return true;

        uint b = ChainUtils.getBlockNumber();
        address cb = storageT.callbacks();

        if (orderType == StorageInterfaceV5.LimitOrder.TP)
            return !cb.isTpInTimeout(
                id,
                b
            );

        if (orderType == StorageInterfaceV5.LimitOrder.SL)
            return !cb.isSlInTimeout(
                id,
                b
            );

        return !cb.isLimitInTimeout(
            id,
            b
        );
    }
}

File 2 of 13 : ChainlinkFeedInterfaceV5.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

interface ChainlinkFeedInterfaceV5{
    function latestRoundData() external view returns (uint80,int,uint,uint,uint80);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

interface GNSPairInfosInterfaceV6{
    function maxNegativePnlOnOpenP() external view returns(uint); // PRECISION (%)

    function storeTradeInitialAccFees(
        address trader,
        uint pairIndex,
        uint index,
        bool long
    ) external;

    function getTradePriceImpact(
        uint openPrice,   // PRECISION
        uint pairIndex,
        bool long,
        uint openInterest // 1e18 (DAI)
    ) external view returns(
        uint priceImpactP,      // PRECISION (%)
        uint priceAfterImpact   // PRECISION
    );

   function getTradeLiquidationPrice(
        address trader,
        uint pairIndex,
        uint index,
        uint openPrice,  // PRECISION
        bool long,
        uint collateral, // 1e18 (DAI)
        uint leverage
    ) external view returns(uint); // PRECISION

    function getTradeValue(
        address trader,
        uint pairIndex,
        uint index,
        bool long,
        uint collateral,   // 1e18 (DAI)
        uint leverage,
        int percentProfit, // PRECISION (%)
        uint closingFee    // 1e18 (DAI)
    ) external returns(uint); // 1e18 (DAI)
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

interface GNSReferralsInterfaceV6_2{
    function registerPotentialReferrer(address trader, address referral) external;
   	function distributePotentialReward(
        address trader,
        uint volumeDai,
        uint pairOpenFeeP,
        uint tokenPriceDai
    ) external returns(uint);
    function getPercentOfOpenFeeP(address trader) external view returns(uint);
    function getTraderReferrer(address trader) external view returns(address referrer);
}

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.21 <0.9.0;

/**
* @title Precompiled contract that exists in every Arbitrum chain at address(100), 0x0000000000000000000000000000000000000064. Exposes a variety of system-level functionality.
 */
interface IArbSys {
    /**
    * @notice Get internal version number identifying an ArbOS build
    * @return version number as int
     */
    function arbOSVersion() external pure returns (uint);

    function arbChainID() external view returns(uint);

    /**
    * @notice Get Arbitrum block number (distinct from L1 block number; Arbitrum genesis block has block number 0)
    * @return block number as int
     */
    function arbBlockNumber() external view returns (uint);

    /** 
    * @notice Send given amount of Eth to dest from sender.
    * This is a convenience function, which is equivalent to calling sendTxToL1 with empty calldataForL1.
    * @param destination recipient address on L1
    * @return unique identifier for this L2-to-L1 transaction.
    */
    function withdrawEth(address destination) external payable returns(uint);

    /** 
    * @notice Send a transaction to L1
    * @param destination recipient address on L1 
    * @param calldataForL1 (optional) calldata for L1 contract call
    * @return a unique identifier for this L2-to-L1 transaction.
    */
    function sendTxToL1(address destination, bytes calldata calldataForL1) external payable returns(uint);

    /** 
    * @notice get the number of transactions issued by the given external account or the account sequence number of the given contract
    * @param account target account
    * @return the number of transactions issued by the given external account or the account sequence number of the given contract
    */
    function getTransactionCount(address account) external view returns(uint256);

    /**  
    * @notice get the value of target L2 storage slot 
    * This function is only callable from address 0 to prevent contracts from being able to call it
    * @param account target account
    * @param index target index of storage slot 
    * @return stotage value for the given account at the given index
    */
    function getStorageAt(address account, uint256 index) external view returns (uint256);

    /**
    * @notice check if current call is coming from l1
    * @return true if the caller of this was called directly from L1
    */
    function isTopLevelCall() external view returns (bool);

    /**
     * @notice check if the caller (of this caller of this) is an aliased L1 contract address
     * @return true iff the caller's address is an alias for an L1 contract address
     */
    function wasMyCallersAddressAliased() external view returns (bool);

    /**
     * @notice return the address of the caller (of this caller of this), without applying L1 contract address aliasing
     * @return address of the caller's caller, without applying L1 contract address aliasing
     */
    function myCallersAddressWithoutAliasing() external view returns (address);

    /**
     * @notice map L1 sender contract address to its L2 alias
     * @param sender sender address
     * @param dest destination address
     * @return aliased sender address
     */
    function mapL1SenderContractAddressToL2Alias(address sender, address dest) external pure returns(address);

    /**
     * @notice get the caller's amount of available storage gas
     * @return amount of storage gas available to the caller
     */
    function getStorageGasAvailable() external view returns(uint);

    event L2ToL1Transaction(address caller, address indexed destination, uint indexed uniqueId,
        uint indexed batchNumber, uint indexInBatch,
        uint arbBlockNum, uint ethBlockNum, uint timestamp,
        uint callvalue, bytes data);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

interface IGToken{
    function manager() external view returns(address);
    function admin() external view returns(address);
    function currentEpoch() external view returns(uint);
    function currentEpochStart() external view returns(uint);
    function currentEpochPositiveOpenPnl() external view returns(uint);
    function updateAccPnlPerTokenUsed(uint prevPositiveOpenPnl, uint newPositiveOpenPnl) external returns(uint);

    struct LockedDeposit {
        address owner;
        uint shares;          // 1e18
        uint assetsDeposited; // 1e18
        uint assetsDiscount;  // 1e18
        uint atTimestamp;     // timestamp
        uint lockDuration;    // timestamp
    }
    function getLockedDeposit(uint depositId) external view returns(LockedDeposit memory);

    function sendAssets(uint assets, address receiver) external;
    function receiveAssets(uint assets, address user) external;
    function distributeReward(uint assets) external;

    function currentBalanceDai() external view returns(uint);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

interface NftInterfaceV5{
    function balanceOf(address) external view returns (uint);
    function ownerOf(uint) external view returns (address);
    function transferFrom(address, address, uint) external;
    function tokenOfOwnerByIndex(address, uint) external view returns(uint);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

interface PairsStorageInterfaceV6{
    enum FeedCalculation { DEFAULT, INVERT, COMBINE }    // FEED 1, 1 / (FEED 1), (FEED 1)/(FEED 2)
    struct Feed{ address feed1; address feed2; FeedCalculation feedCalculation; uint maxDeviationP; } // PRECISION (%)
    function incrementCurrentOrderId() external returns(uint);
    function updateGroupCollateral(uint, uint, bool, bool) external;
    function pairJob(uint) external returns(string memory, string memory, bytes32, uint);
    function pairFeed(uint) external view returns(Feed memory);
    function pairSpreadP(uint) external view returns(uint);
    function pairMinLeverage(uint) external view returns(uint);
    function pairMaxLeverage(uint) external view returns(uint);
    function groupMaxCollateral(uint) external view returns(uint);
    function groupCollateral(uint, bool) external view returns(uint);
    function guaranteedSlEnabled(uint) external view returns(bool);
    function pairOpenFeeP(uint) external view returns(uint);
    function pairCloseFeeP(uint) external view returns(uint);
    function pairOracleFeeP(uint) external view returns(uint);
    function pairNftLimitOrderFeeP(uint) external view returns(uint);
    function pairReferralFeeP(uint) external view returns(uint);
    function pairMinLevPosDai(uint) external view returns(uint);
}

File 9 of 13 : StorageInterfaceV5.sol
// SPDX-License-Identifier: MIT
import './TokenInterfaceV5.sol';
import './NftInterfaceV5.sol';
import './IGToken.sol';
import './PairsStorageInterfaceV6.sol';
import './ChainlinkFeedInterfaceV5.sol';

pragma solidity 0.8.17;

interface PoolInterfaceV5{
    function increaseAccTokensPerLp(uint) external;
}

interface PausableInterfaceV5{
    function isPaused() external view returns (bool);
}

interface StorageInterfaceV5{
    enum LimitOrder { TP, SL, LIQ, OPEN }
    struct Trade{
        address trader;
        uint pairIndex;
        uint index;
        uint initialPosToken;       // 1e18
        uint positionSizeDai;       // 1e18
        uint openPrice;             // PRECISION
        bool buy;
        uint leverage;
        uint tp;                    // PRECISION
        uint sl;                    // PRECISION
    }
    struct TradeInfo{
        uint tokenId;
        uint tokenPriceDai;         // PRECISION
        uint openInterestDai;       // 1e18
        uint tpLastUpdated;
        uint slLastUpdated;
        bool beingMarketClosed;
    }
    struct OpenLimitOrder{
        address trader;
        uint pairIndex;
        uint index;
        uint positionSize;          // 1e18 (DAI or GFARM2)
        uint spreadReductionP;
        bool buy;
        uint leverage;
        uint tp;                    // PRECISION (%)
        uint sl;                    // PRECISION (%)
        uint minPrice;              // PRECISION
        uint maxPrice;              // PRECISION
        uint block;
        uint tokenId;               // index in supportedTokens
    }
    struct PendingMarketOrder{
        Trade trade;
        uint block;
        uint wantedPrice;           // PRECISION
        uint slippageP;             // PRECISION (%)
        uint spreadReductionP;
        uint tokenId;               // index in supportedTokens
    }
    struct PendingNftOrder{
        address nftHolder;
        uint nftId;
        address trader;
        uint pairIndex;
        uint index;
        LimitOrder orderType;
    }
    function PRECISION() external pure returns(uint);
    function gov() external view returns(address);
    function dev() external view returns(address);
    function dai() external view returns(TokenInterfaceV5);
    function token() external view returns(TokenInterfaceV5);
    function linkErc677() external view returns(TokenInterfaceV5);
    function priceAggregator() external view returns(AggregatorInterfaceV6_2);
    function vault() external view returns(IGToken);
    function trading() external view returns(address);
    function callbacks() external view returns(address);
    function handleTokens(address,uint,bool) external;
    function transferDai(address, address, uint) external;
    function transferLinkToAggregator(address, uint, uint) external;
    function unregisterTrade(address, uint, uint) external;
    function unregisterPendingMarketOrder(uint, bool) external;
    function unregisterOpenLimitOrder(address, uint, uint) external;
    function hasOpenLimitOrder(address, uint, uint) external view returns(bool);
    function storePendingMarketOrder(PendingMarketOrder memory, uint, bool) external;
    function openTrades(address, uint, uint) external view returns(Trade memory);
    function openTradesInfo(address, uint, uint) external view returns(TradeInfo memory);
    function updateSl(address, uint, uint, uint) external;
    function updateTp(address, uint, uint, uint) external;
    function getOpenLimitOrder(address, uint, uint) external view returns(OpenLimitOrder memory);
    function spreadReductionsP(uint) external view returns(uint);
    function storeOpenLimitOrder(OpenLimitOrder memory) external;
    function reqID_pendingMarketOrder(uint) external view returns(PendingMarketOrder memory);
    function storePendingNftOrder(PendingNftOrder memory, uint) external;
    function updateOpenLimitOrder(OpenLimitOrder calldata) external;
    function firstEmptyTradeIndex(address, uint) external view returns(uint);
    function firstEmptyOpenLimitIndex(address, uint) external view returns(uint);
    function increaseNftRewards(uint, uint) external;
    function nftSuccessTimelock() external view returns(uint);
    function reqID_pendingNftOrder(uint) external view returns(PendingNftOrder memory);
    function updateTrade(Trade memory) external;
    function nftLastSuccess(uint) external view returns(uint);
    function unregisterPendingNftOrder(uint) external;
    function handleDevGovFees(uint, uint, bool, bool) external returns(uint);
    function distributeLpRewards(uint) external;
    function storeTrade(Trade memory, TradeInfo memory) external;
    function openLimitOrdersCount(address, uint) external view returns(uint);
    function openTradesCount(address, uint) external view returns(uint);
    function pendingMarketOpenCount(address, uint) external view returns(uint);
    function pendingMarketCloseCount(address, uint) external view returns(uint);
    function maxTradesPerPair() external view returns(uint);
    function pendingOrderIdsCount(address) external view returns(uint);
    function maxPendingMarketOrders() external view returns(uint);
    function openInterestDai(uint, uint) external view returns(uint);
    function getPendingOrderIds(address) external view returns(uint[] memory);
    function nfts(uint) external view returns(NftInterfaceV5);
    function fakeBlockNumber() external view returns(uint); // Testing
}

interface IStateCopyUtils {
    function getOpenLimitOrders() external view returns(StorageInterfaceV5.OpenLimitOrder[] memory);
    function nftRewards() external view returns(NftRewardsInterfaceV6_3_1);
}

interface AggregatorInterfaceV6_2{
    enum OrderType { MARKET_OPEN, MARKET_CLOSE, LIMIT_OPEN, LIMIT_CLOSE, UPDATE_SL }
    function pairsStorage() external view returns(PairsStorageInterfaceV6);
    function getPrice(uint,OrderType,uint) external returns(uint);
    function tokenPriceDai() external returns(uint);
    function linkFee(uint,uint) external view returns(uint);
    function openFeeP(uint) external view returns(uint);
    function pendingSlOrders(uint) external view returns(PendingSl memory);
    function storePendingSlOrder(uint orderId, PendingSl calldata p) external;
    function unregisterPendingSlOrder(uint orderId) external;
    struct PendingSl{address trader; uint pairIndex; uint index; uint openPrice; bool buy; uint newSl; }
}

interface AggregatorInterfaceV6_3_1 is AggregatorInterfaceV6_2 {
    function linkPriceFeed() external view returns (ChainlinkFeedInterfaceV5);
}

interface NftRewardsInterfaceV6_3_1{
    struct TriggeredLimitId{ address trader; uint pairIndex; uint index; StorageInterfaceV5.LimitOrder order; }
    enum OpenLimitOrderType{ LEGACY, REVERSAL, MOMENTUM }
    function storeFirstToTrigger(TriggeredLimitId calldata, address, uint) external;
    function storeTriggerSameBlock(TriggeredLimitId calldata, address) external;
    function unregisterTrigger(TriggeredLimitId calldata) external;
    function distributeNftReward(TriggeredLimitId calldata, uint, uint) external;
    function openLimitOrderTypes(address, uint, uint) external view returns(OpenLimitOrderType);
    function setOpenLimitOrderType(address, uint, uint, OpenLimitOrderType) external;
    function triggered(TriggeredLimitId calldata) external view returns(bool);
    function timedOut(TriggeredLimitId calldata) external view returns(bool);
    function botInUse(bytes32) external view returns(bool);
    function getNftBotHashes(uint, address, uint, address, uint, uint) external pure returns(bytes32, bytes32);
    function setNftBotInUse(bytes32, bytes32) external;
    function nftBotInUse(bytes32, bytes32) external view returns(bool);
    function linkToTokenRewards(uint, uint) external view returns(uint);
}

interface TradingCallbacksV6_3_1 {
    enum TradeType {MARKET, LIMIT}
    struct SimplifiedTradeId{ address trader; uint pairIndex; uint index; TradeType tradeType; }
    struct LastUpdated{ uint32 tp; uint32 sl; uint32 limit; uint32 created; }
    function tradeLastUpdated(address, uint, uint, TradeType) external view returns(LastUpdated memory);
    function setTradeLastUpdated(SimplifiedTradeId calldata, LastUpdated memory) external;
    function canExecuteTimeout() external view returns(uint);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

interface TokenInterfaceV5{
    function burn(address, uint256) external;
    function mint(address, uint256) external;
    function transfer(address, uint256) external returns (bool);
    function transferFrom(address, address, uint256) external returns(bool);
    function balanceOf(address) external view returns(uint256);
    function hasRole(bytes32, address) external view returns (bool);
    function approve(address, uint256) external returns (bool);
    function allowance(address, address) external view returns (uint256);
}

File 11 of 13 : ChainUtils.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import "../interfaces/IArbSys.sol";

library ChainUtils {

    uint256 constant public ARBITRUM_MAINNET = 42161;
    uint256 constant public ARBITRUM_GOERLI = 421613;
    IArbSys constant public ARB_SYS = IArbSys(address(100));

    function getBlockNumber() internal view returns (uint) {
        if (block.chainid == ARBITRUM_MAINNET || block.chainid == ARBITRUM_GOERLI) {
            return ARB_SYS.arbBlockNumber();
        }

        return block.number;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import '../interfaces/StorageInterfaceV5.sol';

library TradeUtils {
    function _getTradeLastUpdated(
        address _callbacks,
        address trader,
        uint pairIndex,
        uint index,
        TradingCallbacksV6_3_1.TradeType _type
    ) internal view returns (
        TradingCallbacksV6_3_1,
        TradingCallbacksV6_3_1.LastUpdated memory,
        TradingCallbacksV6_3_1.SimplifiedTradeId memory
    ) {
        TradingCallbacksV6_3_1 callbacks = TradingCallbacksV6_3_1(_callbacks);
        TradingCallbacksV6_3_1.LastUpdated memory l = callbacks.tradeLastUpdated(trader, pairIndex, index, _type);

        return (callbacks, l, TradingCallbacksV6_3_1.SimplifiedTradeId(trader, pairIndex, index, _type));
    }

    function getTradeLastUpdated(
        address _callbacks,
        address trader,
        uint pairIndex,
        uint index,
        TradingCallbacksV6_3_1.TradeType _type
    ) external view returns (
        TradingCallbacksV6_3_1,
        TradingCallbacksV6_3_1.LastUpdated memory,
        TradingCallbacksV6_3_1.SimplifiedTradeId memory
    ) {
        return _getTradeLastUpdated(_callbacks, trader, pairIndex, index, _type);
    }

    function setTradeLastUpdated(
        address _callbacks,
        address trader,
        uint pairIndex,
        uint index,
        TradingCallbacksV6_3_1.TradeType _type,
        uint blockNumber
    ) external {
        uint32 b = uint32(blockNumber);
        TradingCallbacksV6_3_1 callbacks = TradingCallbacksV6_3_1(_callbacks);
        callbacks.setTradeLastUpdated(
            TradingCallbacksV6_3_1.SimplifiedTradeId(trader, pairIndex, index, _type),
            TradingCallbacksV6_3_1.LastUpdated(b, b, b, b)
        );
    }

    function setSlLastUpdated(
        address _callbacks,
        address trader,
        uint pairIndex,
        uint index,
        TradingCallbacksV6_3_1.TradeType _type,
        uint blockNumber
    ) external {
        (
            TradingCallbacksV6_3_1 callbacks,
            TradingCallbacksV6_3_1.LastUpdated memory l,
            TradingCallbacksV6_3_1.SimplifiedTradeId memory id
        ) = _getTradeLastUpdated(_callbacks, trader, pairIndex, index, _type);

        l.sl = uint32(blockNumber);
        callbacks.setTradeLastUpdated(id, l);
    }

    function setTpLastUpdated(
        address _callbacks,
        address trader,
        uint pairIndex,
        uint index,
        TradingCallbacksV6_3_1.TradeType _type,
        uint blockNumber
    ) external {
        (
            TradingCallbacksV6_3_1 callbacks,
            TradingCallbacksV6_3_1.LastUpdated memory l,
            TradingCallbacksV6_3_1.SimplifiedTradeId memory id
        ) = _getTradeLastUpdated(
            _callbacks, trader, pairIndex, index, _type
        );

        l.tp = uint32(blockNumber);
        callbacks.setTradeLastUpdated(id, l);
    }

    function setLimitLastUpdated(
        address _callbacks,
        address trader,
        uint pairIndex,
        uint index,
        TradingCallbacksV6_3_1.TradeType _type,
        uint blockNumber
    ) external {
        (
            TradingCallbacksV6_3_1 callbacks,
            TradingCallbacksV6_3_1.LastUpdated memory l,
            TradingCallbacksV6_3_1.SimplifiedTradeId memory id
        ) = _getTradeLastUpdated(
            _callbacks, trader, pairIndex, index, _type
        );

        l.limit = uint32(blockNumber);
        callbacks.setTradeLastUpdated(id, l);
    }

    function isTpInTimeout(
        address _callbacks,
        TradingCallbacksV6_3_1.SimplifiedTradeId memory id,
        uint currentBlock
    ) external view returns (bool) {
        (
            TradingCallbacksV6_3_1 callbacks,
            TradingCallbacksV6_3_1.LastUpdated memory l,
        ) = _getTradeLastUpdated(
            _callbacks, id.trader, id.pairIndex, id.index, id.tradeType
        );

        return currentBlock < uint256(l.tp) + callbacks.canExecuteTimeout();
    }

    function isSlInTimeout(
        address _callbacks,
        TradingCallbacksV6_3_1.SimplifiedTradeId memory id,
        uint currentBlock
    ) external view returns (bool) {
        (
            TradingCallbacksV6_3_1 callbacks,
            TradingCallbacksV6_3_1.LastUpdated memory l,
        ) = _getTradeLastUpdated(
            _callbacks, id.trader, id.pairIndex, id.index, id.tradeType
        );

        return currentBlock < uint256(l.sl) + callbacks.canExecuteTimeout();
    }

    function isLimitInTimeout(
        address _callbacks,
        TradingCallbacksV6_3_1.SimplifiedTradeId memory id,
        uint currentBlock
    ) external view returns (bool) {
        (
            TradingCallbacksV6_3_1 callbacks,
            TradingCallbacksV6_3_1.LastUpdated memory l,
        ) = _getTradeLastUpdated(
            _callbacks, id.trader, id.pairIndex, id.index, id.tradeType
        );

        return currentBlock < uint256(l.limit) + callbacks.canExecuteTimeout();
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

abstract contract Delegatable {
    mapping (address => address) public delegations;
    address private senderOverride;

    function setDelegate(address delegate) external {
        require(tx.origin == msg.sender, "NO_CONTRACT");

        delegations[msg.sender] = delegate;
    }

    function removeDelegate() external {
        delegations[msg.sender] = address(0);
    }

    function delegatedAction(address trader, bytes calldata call_data) external returns (bytes memory) {
        require(delegations[trader] == msg.sender, "DELEGATE_NOT_APPROVED");

        senderOverride = trader;
        (bool success, bytes memory result) = address(this).delegatecall(call_data);
        if (!success) {
            // Next 5 lines from https://ethereum.stackexchange.com/a/83577 (return the original revert reason)
            if (result.length < 68) revert();
            assembly {
                result := add(result, 0x04)
            }
            revert(abi.decode(result, (string)));
        }

        senderOverride = address(0);

        return result;
    }


    function _msgSender() public view returns (address) {
        if (senderOverride == address(0)) {
            return msg.sender;
        } else {
            return senderOverride;
        }
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 275
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {
    "contracts/libraries/TradeUtils.sol": {
      "TradeUtils": "0x7ca99c35586739c7f14191a8a00f072ff804e4c7"
    }
  }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract StorageInterfaceV5","name":"_storageT","type":"address"},{"internalType":"contract NftRewardsInterfaceV6_3_1","name":"_nftRewards","type":"address"},{"internalType":"contract GNSPairInfosInterfaceV6","name":"_pairInfos","type":"address"},{"internalType":"contract GNSReferralsInterfaceV6_2","name":"_referrals","type":"address"},{"internalType":"uint256","name":"_maxPosDai","type":"uint256"},{"internalType":"uint256","name":"_marketOrdersTimeout","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"orderId","type":"uint256"},{"components":[{"components":[{"internalType":"address","name":"trader","type":"address"},{"internalType":"uint256","name":"pairIndex","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"initialPosToken","type":"uint256"},{"internalType":"uint256","name":"positionSizeDai","type":"uint256"},{"internalType":"uint256","name":"openPrice","type":"uint256"},{"internalType":"bool","name":"buy","type":"bool"},{"internalType":"uint256","name":"leverage","type":"uint256"},{"internalType":"uint256","name":"tp","type":"uint256"},{"internalType":"uint256","name":"sl","type":"uint256"}],"internalType":"struct StorageInterfaceV5.Trade","name":"trade","type":"tuple"},{"internalType":"uint256","name":"block","type":"uint256"},{"internalType":"uint256","name":"wantedPrice","type":"uint256"},{"internalType":"uint256","name":"slippageP","type":"uint256"},{"internalType":"uint256","name":"spreadReductionP","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"indexed":false,"internalType":"struct StorageInterfaceV5.PendingMarketOrder","name":"order","type":"tuple"}],"name":"ChainlinkCallbackTimeout","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":true,"internalType":"uint256","name":"pairIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"CouldNotCloseTrade","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"done","type":"bool"}],"name":"Done","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"orderId","type":"uint256"},{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":true,"internalType":"uint256","name":"pairIndex","type":"uint256"},{"indexed":false,"internalType":"bool","name":"open","type":"bool"}],"name":"MarketOrderInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"orderId","type":"uint256"},{"indexed":true,"internalType":"address","name":"nftHolder","type":"address"},{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":true,"internalType":"uint256","name":"pairIndex","type":"uint256"}],"name":"NftOrderInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nftHolder","type":"address"},{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":true,"internalType":"uint256","name":"pairIndex","type":"uint256"}],"name":"NftOrderSameBlock","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"NumberUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":true,"internalType":"uint256","name":"pairIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"OpenLimitCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":true,"internalType":"uint256","name":"pairIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"OpenLimitPlaced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":true,"internalType":"uint256","name":"pairIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newSl","type":"uint256"}],"name":"OpenLimitUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"orderId","type":"uint256"},{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":true,"internalType":"uint256","name":"pairIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newSl","type":"uint256"}],"name":"SlUpdateInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":true,"internalType":"uint256","name":"pairIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newSl","type":"uint256"}],"name":"SlUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":true,"internalType":"uint256","name":"pairIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTp","type":"uint256"}],"name":"TpUpdated","type":"event"},{"inputs":[],"name":"_msgSender","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"pairIndex","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"cancelOpenLimitOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pairIndex","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"closeTradeMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_order","type":"uint256"}],"name":"closeTradeMarketTimeout","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"trader","type":"address"},{"internalType":"bytes","name":"call_data","type":"bytes"}],"name":"delegatedAction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"delegations","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"done","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum StorageInterfaceV5.LimitOrder","name":"orderType","type":"uint8"},{"internalType":"address","name":"trader","type":"address"},{"internalType":"uint256","name":"pairIndex","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"nftId","type":"uint256"},{"internalType":"uint256","name":"nftType","type":"uint256"}],"name":"executeNftOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isDone","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketOrdersTimeout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPosDai","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nftRewards","outputs":[{"internalType":"contract NftRewardsInterfaceV6_3_1","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"trader","type":"address"},{"internalType":"uint256","name":"pairIndex","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"initialPosToken","type":"uint256"},{"internalType":"uint256","name":"positionSizeDai","type":"uint256"},{"internalType":"uint256","name":"openPrice","type":"uint256"},{"internalType":"bool","name":"buy","type":"bool"},{"internalType":"uint256","name":"leverage","type":"uint256"},{"internalType":"uint256","name":"tp","type":"uint256"},{"internalType":"uint256","name":"sl","type":"uint256"}],"internalType":"struct StorageInterfaceV5.Trade","name":"t","type":"tuple"},{"internalType":"enum NftRewardsInterfaceV6_3_1.OpenLimitOrderType","name":"orderType","type":"uint8"},{"internalType":"uint256","name":"spreadReductionId","type":"uint256"},{"internalType":"uint256","name":"slippageP","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"}],"name":"openTrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_order","type":"uint256"}],"name":"openTradeMarketTimeout","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pairInfos","outputs":[{"internalType":"contract GNSPairInfosInterfaceV6","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"referrals","outputs":[{"internalType":"contract GNSReferralsInterfaceV6_2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"removeDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"}],"name":"setDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"setMarketOrdersTimeout","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"setMaxPosDai","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"storageT","outputs":[{"internalType":"contract StorageInterfaceV5","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"pairIndex","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"tp","type":"uint256"},{"internalType":"uint256","name":"sl","type":"uint256"}],"name":"updateOpenLimitOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pairIndex","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"newSl","type":"uint256"}],"name":"updateSl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pairIndex","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"newTp","type":"uint256"}],"name":"updateTp","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6101006040523480156200001257600080fd5b50604051620061ba380380620061ba833981016040819052620000359162000122565b6001600160a01b038616158015906200005657506001600160a01b03851615155b80156200006b57506001600160a01b03841615155b80156200008057506001600160a01b03831615155b80156200008d5750600082115b80156200009a5750600081115b620000da5760405162461bcd60e51b815260206004820152600c60248201526b57524f4e475f504152414d5360a01b604482015260640160405180910390fd5b6001600160a01b0395861660805293851660a05291841660c05290921660e0526002919091556003556200019e565b6001600160a01b03811681146200011f57600080fd5b50565b60008060008060008060c087890312156200013c57600080fd5b8651620001498162000109565b60208801519096506200015c8162000109565b60408801519095506200016f8162000109565b6060880151909450620001828162000109565b809350506080870151915060a087015190509295509295509295565b60805160a05160c05160e051615df1620003c9600039600081816103cf01526124440152600081816101bd01528181611b0c01528181611bd1015281816133450152818161387401526138e301526000818161026201528181611fae01528181612f5201528181612fde015281816130a80152818161365a015281816136ee01528181613d1801528181613e5001528181614d210152614db50152600081816101e401528181610460015281816105300152818161069801528181610701015281816108f501528181610a8701528181610b0701528181610c9701528181610e27015281816111950152818161128b01528181611337015281816113d0015281816114690152818161152f015281816115ce015281816118db01528181611cca01528181611d8301528181611df201528181611e6d0152818161202301528181612208015281816122e3015281816124cb01528181612561015281816125f401528181612693015281816127cc015281816128f501528181612bcb01528181612d0901528181612d9f0152818161319f0152818161326c015281816133930152818161379e015281816139cc01528181613a9c01528181613b0b01528181613c2801528181613f3a01528181614005015281816140a60152818161412d0152818161422d015281816142ae01528181614428015281816145bd0152818161461b015281816149df01528181614acf01528181614b2d01528181614ef80152614ff60152615df16000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80639a10cc32116100de578063b8ebd5cc11610097578063bffe348611610071578063bffe34861461038e578063ca5eb5e1146103b7578063d3dc7539146103ca578063d8defd15146103f157600080fd5b8063b8ebd5cc14610355578063b9b6573a14610368578063be73fb991461037b57600080fd5b80639a10cc32146102e75780639aa7c0e514610307578063a2a3c0cb1461031a578063ae8421e11461032d578063b187bd2614610335578063b81bfa051461034257600080fd5b8063410c0b7c1161014b578063876d3abd11610125578063876d3abd1461028c5780638f0622271461029f578063934d1cf4146102c1578063990382cf146102d457600080fd5b8063410c0b7c146102545780635ad9f9931461025d5780638456cb591461028457600080fd5b8063119df25f146101935780631346b0ff146101b857806316fff074146101df578063279a165c14610206578063318a368b1461021d57806336fb8b1514610232575b600080fd5b61019b610404565b6040516001600160a01b0390911681526020015b60405180910390f35b61019b7f000000000000000000000000000000000000000000000000000000000000000081565b61019b7f000000000000000000000000000000000000000000000000000000000000000081565b61020f60025481565b6040519081526020016101af565b61023061022b36600461520d565b61042c565b005b61023033600090815260208190526040902080546001600160a01b0319169055565b61020f60035481565b61019b7f000000000000000000000000000000000000000000000000000000000000000081565b610230610861565b61023061029a366004615248565b6108b7565b6004546102b190610100900460ff1681565b60405190151581526020016101af565b6102306102cf366004615248565b610bb8565b6102306102e2366004615248565b610c59565b6102fa6102f5366004615289565b610fb7565b6040516101af919061535e565b610230610315366004615404565b6110fa565b6102306103283660046154e3565b6124ab565b610230612a4e565b6004546102b19060ff1681565b610230610350366004615248565b612aae565b610230610363366004615505565b612b52565b6102306103763660046154e3565b613f06565b610230610389366004615562565b6141ea565b61019b61039c36600461558e565b6000602081905290815260409020546001600160a01b031681565b6102306103c536600461558e565b614930565b61019b7f000000000000000000000000000000000000000000000000000000000000000081565b6102306103ff366004615562565b61499c565b6001546000906001600160a01b031661041c57503390565b506001546001600160a01b031690565b610434614c7c565b61043c614c8a565b6000610446610404565b604051636e6f99cd60e11b81529091506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063dcdf339a906104999084908a908a906004016155ab565b602060405180830381865afa1580156104b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104da91906155d7565b6105165760405162461bcd60e51b81526020600482015260086024820152671393d7d31253525560c21b60448201526064015b60405180910390fd5b604051632e21e28b60e21b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b8878a2c906105699085908b908b906004016155ab565b6101a060405180830381865afa158015610587573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ab91906155ff565b90508315806105ca57508060a001516105c6578484106105ca565b8484115b6106015760405162461bcd60e51b8152602060048201526008602482015267057524f4e475f54560c41b604482015260640161050d565b82158061061e57508060a0015161061a5784831161061e565b8483105b6106555760405162461bcd60e51b815260206004820152600860248201526715d493d391d7d4d360c21b604482015260640161050d565b6106628288886003614ccb565b6101208101859052610140810185905260e081018490526101008101839052604051635bb3b04560e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b767608a906106cd9084906004016156b2565b600060405180830381600087803b1580156106e757600080fd5b505af11580156106fb573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031662b127836040518163ffffffff1660e01b8152600401602060405180830381865afa15801561075c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107809190615752565b6001600160a01b0316737ca99c35586739c7f14191a8a00f072ff804e4c7634863c9c39091848a8a60016107b2614e70565b6040518763ffffffff1660e01b81526004016107d396959493929190615799565b60006040518083038186803b1580156107eb57600080fd5b505af41580156107ff573d6000803e3d6000fd5b50506040805189815260208101899052908101879052606081018690528992506001600160a01b03851691507f21e15d62c2ece17c1dc11c5fa45dcefdc6f99f199aa111d1363ff242f23e1c5c9060800160405180910390a350505050505050565b610869614ef6565b6004805460ff8082161560ff1990921682179092556040519116151581527f0e2fb031ee032dc02d8011dc50b816eb450cf856abd8261680dac74f72165bd2906020015b60405180910390a1565b6108bf614c7c565b6108c7614c8a565b60006108d1610404565b60405163b66e6b0560e01b8152600481018490529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b66e6b05906024016101e060405180830381865afa15801561093d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109619190615870565b80516020820151919250901580159061098b575060035482602001516109879190615909565b4310155b6109c65760405162461bcd60e51b815260206004820152600c60248201526b15d0525517d512535153d55560a21b604482015260640161050d565b826001600160a01b031681600001516001600160a01b031614610a1c5760405162461bcd60e51b815260206004820152600e60248201526d2727aa2faca7aaa92fa7a92222a960911b604482015260640161050d565b60008160e0015111610a6a5760405162461bcd60e51b815260206004820152601760248201527657524f4e475f4d41524b45545f4f524445525f5459504560481b604482015260640161050d565b604051630195728b60e71b815260048101859052600160248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063cab9458090604401600060405180830381600087803b158015610ad357600080fd5b505af1158015610ae7573d6000803e3d6000fd5b50505050608081015160405163373873db60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830181905290861660248301526044820192909252636e70e7b690606401600060405180830381600087803b158015610b6257600080fd5b505af1158015610b76573d6000803e3d6000fd5b50505050837f3adaa586cdbe84dd24e45bd7dada6da933d7c2d1c7b4e4cd02fce033356decb183604051610baa91906159ca565b60405180910390a250505050565b610bc0614ef6565b60008111610bfa5760405162461bcd60e51b8152602060048201526007602482015266056414c55455f360cc1b604482015260640161050d565b600281905560408051818152600991810191909152686d6178506f7344616960b81b6060820152602081018290527f8cf3e35f6221b16e1670a3413180c9484bf5aa71787905909fa82a6a2662e9ab906080015b60405180910390a150565b610c61614c7c565b610c69614c8a565b6000610c73610404565b60405163b66e6b0560e01b8152600481018490529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b66e6b05906024016101e060405180830381865afa158015610cdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d039190615870565b805160208201519192509015801590610d2d57506003548260200151610d299190615909565b4310155b610d685760405162461bcd60e51b815260206004820152600c60248201526b15d0525517d512535153d55560a21b604482015260640161050d565b826001600160a01b031681600001516001600160a01b031614610dbe5760405162461bcd60e51b815260206004820152600e60248201526d2727aa2faca7aaa92fa7a92222a960911b604482015260640161050d565b60e081015115610e0a5760405162461bcd60e51b815260206004820152601760248201527657524f4e475f4d41524b45545f4f524445525f5459504560481b604482015260640161050d565b604051630195728b60e71b815260048101859052600060248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063cab9458090604401600060405180830381600087803b158015610e7357600080fd5b505af1158015610e87573d6000803e3d6000fd5b505050602082015160408084015190516024810192909252604482015260009150309060640160408051601f198184030181529181526020820180516001600160e01b031663a2a3c0cb60e01b17905251610ee291906159d9565b600060405180830381855af49150503d8060008114610f1d576040519150601f19603f3d011682016040523d82523d6000602084013e610f22565b606091505b5050905080610f78578160200151846001600160a01b03167f60e497734ddabcd7293fd91739aaf65cf525eb539c97be528125a235a89288d88460400151604051610f6f91815260200190565b60405180910390a35b847f3adaa586cdbe84dd24e45bd7dada6da933d7c2d1c7b4e4cd02fce033356decb184604051610fa891906159ca565b60405180910390a25050505050565b6001600160a01b038381166000908152602081905260409020546060911633146110235760405162461bcd60e51b815260206004820152601560248201527f44454c45474154455f4e4f545f415050524f5645440000000000000000000000604482015260640161050d565b600180546001600160a01b0319166001600160a01b0386161790556040516000908190309061105590879087906159f5565b600060405180830381855af49150503d8060008114611090576040519150601f19603f3d011682016040523d82523d6000602084013e611095565b606091505b5091509150816110e1576044815110156110ae57600080fd5b600481019050808060200190518101906110c89190615a05565b60405162461bcd60e51b815260040161050d919061535e565b600180546001600160a01b031916905595945050505050565b611102614c7c565b61110a614c8a565b60045460ff16156111465760405162461bcd60e51b815260206004820152600660248201526514105554d15160d21b604482015260640161050d565b600019828660a001516111599190615ab2565b106111915760405162461bcd60e51b81526020600482015260086024820152674f564552464c4f5760c01b604482015260640161050d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316633078fff56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112159190615752565b90506000816001600160a01b03166335b03c176040518163ffffffff1660e01b8152600401602060405180830381865afa158015611257573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127b9190615752565b90506000611287610404565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f65d9dbe6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130b9190615ac9565b6020890151604051634bf3ccad60e11b81526001600160a01b03848116600483015260248201929092527f0000000000000000000000000000000000000000000000000000000000000000909116906397e7995a90604401602060405180830381865afa158015611380573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a49190615ac9565b60208a0151604051639c8912f160e01b81526001600160a01b03858116600483015260248201929092527f000000000000000000000000000000000000000000000000000000000000000090911690639c8912f190604401602060405180830381865afa158015611419573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061143d9190615ac9565b60208b01516040516307218dad60e21b81526001600160a01b03868116600483015260248201929092527f000000000000000000000000000000000000000000000000000000000000000090911690631c8636b490604401602060405180830381865afa1580156114b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d69190615ac9565b6114e09190615909565b6114ea9190615909565b1061152d5760405162461bcd60e51b815260206004820152601360248201527226a0ac2faa2920a222a9afa822a92fa820a4a960691b604482015260640161050d565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638049fde76040518163ffffffff1660e01b8152600401602060405180830381865afa15801561158b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115af9190615ac9565b60405163f7b3c6fd60e01b81526001600160a01b0383811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063f7b3c6fd90602401602060405180830381865afa158015611615573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116399190615ac9565b1061167b5760405162461bcd60e51b81526020600482015260126024820152714d41585f50454e44494e475f4f524445525360701b604482015260640161050d565b600254886080015111156116c15760405162461bcd60e51b815260206004820152600d60248201526c41424f56455f4d41585f504f5360981b604482015260640161050d565b602088015160405163066c581160e11b815260048101919091526001600160a01b03831690630cd8b02290602401602060405180830381865afa15801561170c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117309190615ac9565b8860e0015189608001516117449190615ab2565b10156117825760405162461bcd60e51b815260206004820152600d60248201526c42454c4f575f4d494e5f504f5360981b604482015260640161050d565b60008860e001511180156118085750602088015160405163059a992d60e41b815260048101919091526001600160a01b038316906359a992d090602401602060405180830381865afa1580156117dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118009190615ac9565b8860e0015110155b801561188657506020880151604051630a06da4f60e21b815260048101919091526001600160a01b0383169063281b693c90602401602060405180830381865afa15801561185a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061187e9190615ac9565b8860e0015111155b6118c75760405162461bcd60e51b815260206004820152601260248201527113115591549051d157d25390d3d4949150d560721b604482015260640161050d565b8515806119d8575060006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663265aa62161190b60018a615ae2565b6040518263ffffffff1660e01b815260040161192991815260200190565b602060405180830381865afa158015611946573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061196a9190615752565b6040516370a0823160e01b81526001600160a01b03848116600483015291909116906370a0823190602401602060405180830381865afa1580156119b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119d69190615ac9565b115b611a325760405162461bcd60e51b815260206004820152602560248201527f4e4f5f434f52524553504f4e44494e475f4e46545f5350524541445f5245445560448201526421aa24a7a760d91b606482015260840161050d565b6101008801511580611a6657508760c00151611a59578760a0015188610100015110611a66565b8760a00151886101000151115b611a9d5760405162461bcd60e51b8152602060048201526008602482015267057524f4e475f54560c41b604482015260640161050d565b6101208801511580611ad157508760c00151611ac4578760a0015188610120015111611ad1565b8760a00151886101200151105b611b085760405162461bcd60e51b815260206004820152600860248201526715d493d391d7d4d360c21b604482015260640161050d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637ea95f3260008b602001518c60c001518d60e001518e60800151611b599190615ab2565b6040516001600160e01b031960e087901b168152600481019490945260248401929092521515604483015260648201526084016040805180830381865afa158015611ba8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bcc9190615af5565b5090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166380f6cfc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c519190615ac9565b60e08a0151611c609083615ab2565b1115611ca65760405162461bcd60e51b81526020600482015260156024820152740a0a492868abe929aa08286a8bea89e9ebe90928e9605b1b604482015260640161050d565b608089015160405163373873db60e11b81526001600160a01b0384811660048301527f000000000000000000000000000000000000000000000000000000000000000016602482018190526044820192909252636e70e7b690606401600060405180830381600087803b158015611d1c57600080fd5b505af1158015611d30573d6000803e3d6000fd5b5060009250611d3d915050565b886002811115611d4f57611d4f61576f565b1461217757602089015160405163226a27ad60e11b81526001600160a01b03848116600483015260248201929092526000917f000000000000000000000000000000000000000000000000000000000000000016906344d44f5a90604401602060405180830381865afa158015611dca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dee9190615ac9565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d3b5fe70604051806101a00160405280866001600160a01b031681526020018d6020015181526020018481526020018d60800151815260200160008c11611e63576000611efc565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016633dae10a0611e9d60018f615ae2565b6040518263ffffffff1660e01b8152600401611ebb91815260200190565b602060405180830381865afa158015611ed8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611efc9190615ac9565b81526020018d60c00151151581526020018d60e0015181526020018d610100015181526020018d610120015181526020018d60a0015181526020018d60a00151815260200143815260200160008152506040518263ffffffff1660e01b8152600401611f6891906156b2565b600060405180830381600087803b158015611f8257600080fd5b505af1158015611f96573d6000803e3d6000fd5b5050505060208a0151604051630ec5706160e41b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163ec57061091611fef91879186908f90600401615b19565b600060405180830381600087803b15801561200957600080fd5b505af115801561201d573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031662b127836040518163ffffffff1660e01b8152600401602060405180830381865afa15801561207e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120a29190615752565b6001600160a01b0316737ca99c35586739c7f14191a8a00f072ff804e4c7634863c9c39091858d602001518560016120d8614e70565b6040518763ffffffff1660e01b81526004016120f996959493929190615799565b60006040518083038186803b15801561211157600080fd5b505af4158015612125573d6000803e3d6000fd5b505050508960200151836001600160a01b03167fdfabd6f206f17b7f2e1f9e0d33c40d30d1e8d7b6a4f520a03fdc1c18110593438360405161216991815260200190565b60405180910390a35061241d565b6000846001600160a01b031663fa8dd4988b6020015160008d60e001518e608001516121a39190615ab2565b6040518463ffffffff1660e01b81526004016121c193929190615b56565b6020604051808303816000875af11580156121e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122049190615ac9565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c76faf786040518060c00160405280604051806101400160405280886001600160a01b031681526020018f60200151815260200160008152602001600081526020018f608001518152602001600081526020018f60c00151151581526020018f60e0015181526020018f610100015181526020018f61012001518152508152602001600081526020018d60a0015181526020018a815260200160008c116122d9576000612372565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016633dae10a061231360018f615ae2565b6040518263ffffffff1660e01b815260040161233191815260200190565b602060405180830381865afa15801561234e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123729190615ac9565b815260200160008152508360016040518463ffffffff1660e01b815260040161239d93929190615b7e565b600060405180830381600087803b1580156123b757600080fd5b505af11580156123cb573d6000803e3d6000fd5b505050508960200151836001600160a01b0316827f3e544118c04e3bb18b669475695cd270ba0e41fb13177483f01c14222de62a866001604051612413911515815260200190565b60405180910390a4505b6040516326e2ada160e21b81526001600160a01b03838116600483015286811660248301527f00000000000000000000000000000000000000000000000000000000000000001690639b8ab68490604401600060405180830381600087803b15801561248857600080fd5b505af115801561249c573d6000803e3d6000fd5b50505050505050505050505050565b6124b3614c7c565b6124bb614c8a565b60006124c5610404565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a3a80ffe8386866040518463ffffffff1660e01b8152600401612519939291906155ab565b61014060405180830381865afa158015612537573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061255b9190615ba5565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638c8ff1d58487876040518463ffffffff1660e01b81526004016125af939291906155ab565b60c060405180830381865afa1580156125cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f09190615bc2565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638049fde76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612650573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126749190615ac9565b60405163f7b3c6fd60e01b81526001600160a01b0385811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063f7b3c6fd90602401602060405180830381865afa1580156126da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fe9190615ac9565b106127405760405162461bcd60e51b81526020600482015260126024820152714d41585f50454e44494e475f4f524445525360701b604482015260640161050d565b8060a00151156127895760405162461bcd60e51b81526020600482015260146024820152731053149150511657d091525391d7d0d313d4d15160621b604482015260640161050d565b60008260e00151116127c85760405162461bcd60e51b81526020600482015260086024820152674e4f5f545241444560c01b604482015260640161050d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316633078fff56040518163ffffffff1660e01b8152600401602060405180830381865afa158015612828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061284c9190615752565b6001600160a01b031663fa8dd4988760016402540be4008760e001518760200151896060015161287c9190615ab2565b6128869190615ab2565b6128909190615c42565b6040518463ffffffff1660e01b81526004016128ae93929190615b56565b6020604051808303816000875af11580156128cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128f19190615ac9565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c76faf786040518060c00160405280604051806101400160405280896001600160a01b031681526020018b81526020018a81526020016000815260200160008152602001600081526020016000151581526020016000815260200160008152602001600081525081526020016000815260200160008152602001600081526020016000815260200160008152508360006040518463ffffffff1660e01b81526004016129cc93929190615b7e565b600060405180830381600087803b1580156129e657600080fd5b505af11580156129fa573d6000803e3d6000fd5b5050505085846001600160a01b0316827f3e544118c04e3bb18b669475695cd270ba0e41fb13177483f01c14222de62a866000604051612a3e911515815260200190565b60405180910390a4505050505050565b612a56614ef6565b6004805460ff610100808304821615810261ff001990931692909217928390556040517fc3a6f986261de9467c2838c6df8ef74f9107855159205600c0bc7a14cdfd3888936108ad9390049091161515815260200190565b612ab6614ef6565b60008111612af05760405162461bcd60e51b8152602060048201526007602482015266056414c55455f360cc1b604482015260640161050d565b600381905560408051818152601391810191909152721b585c9ad95d13dc99195c9cd51a5b595bdd5d606a1b6060820152602081018290527f8cf3e35f6221b16e1670a3413180c9484bf5aa71787905909fa82a6a2662e9ab90608001610c4e565b612b5a614c7c565b612b62614c8a565b6000612b6c610404565b905060018210158015612b80575060058211155b612bbd5760405162461bcd60e51b815260206004820152600e60248201526d57524f4e475f4e46545f5459504560901b604482015260640161050d565b6001600160a01b03808216907f00000000000000000000000000000000000000000000000000000000000000001663265aa621612bfb600186615ae2565b6040518263ffffffff1660e01b8152600401612c1991815260200190565b602060405180830381865afa158015612c36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5a9190615752565b6001600160a01b0316636352211e856040518263ffffffff1660e01b8152600401612c8791815260200190565b602060405180830381865afa158015612ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cc89190615752565b6001600160a01b031614612d075760405162461bcd60e51b81526020600482015260066024820152651393d7d3919560d21b604482015260640161050d565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f8d24b486040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d899190615ac9565b60405163aa3b7d7760e01b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063aa3b7d7790602401602060405180830381865afa158015612dee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e129190615ac9565b612e1c9190615909565b431015612e5e5760405162461bcd60e51b815260206004820152601060248201526f535543434553535f54494d454c4f434b60801b604482015260640161050d565b612ed3876040518060800160405280896001600160a01b03168152602001888152602001878152602001600380811115612e9a57612e9a61576f565b8b6003811115612eac57612eac61576f565b14612eb8576000612ebb565b60015b6001811115612ecc57612ecc61576f565b9052614fc3565b612f0c5760405162461bcd60e51b815260206004820152600a602482015269125397d512535153d55560b21b604482015260640161050d565b60405162c1932360e11b81524360048201526001600160a01b0382811660248301526044820185905287811660648301526084820187905260a4820186905260009182917f0000000000000000000000000000000000000000000000000000000000000000169063018326469060c4016040805180830381865afa158015612f98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fbc9190615af5565b60405163255b694560e21b8152600481018390526024810182905291935091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063956da51490604401602060405180830381865afa15801561302d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061305191906155d7565b1561308b5760405162461bcd60e51b815260206004820152600a602482015269424f545f494e5f55534560b01b604482015260640161050d565b604051630580c65760e41b815260048101839052602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063580c657090604401600060405180830381600087803b1580156130f457600080fd5b505af1158015613108573d6000803e3d6000fd5b50505050505061316f60405180610140016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160008152602001600081525090565b60038860038111156131835761318361576f565b0361325557604051636e6f99cd60e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063dcdf339a906131d8908a908a908a906004016155ab565b602060405180830381865afa1580156131f5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061321991906155d7565b6132505760405162461bcd60e51b81526020600482015260086024820152671393d7d31253525560c21b604482015260640161050d565b613604565b6040516351d407ff60e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a3a80ffe906132a5908a908a908a906004016155ab565b61014060405180830381865afa1580156132c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132e79190615ba5565b905060008160e00151116133285760405162461bcd60e51b81526020600482015260086024820152674e4f5f545241444560c01b604482015260640161050d565b600288600381111561333c5761333c61576f565b036135505760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636bc84d598360000151846020015185604001518660a001518760c001516402540be4007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638c8ff1d58b600001518c602001518d604001516040518463ffffffff1660e01b81526004016133ed939291906155ab565b60c060405180830381865afa15801561340a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342e9190615bc2565b602001518a606001516134419190615ab2565b61344b9190615c42565b60e08a8101516040519189901b6001600160e01b03191682526001600160a01b039790971660048201526024810195909552604485019390935260648401919091521515608483015260a482015260c481019190915260e401602060405180830381865afa1580156134c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134e59190615ac9565b90508161012001516000148061351557508160c0015161350c578161012001518110613515565b81610120015181115b61354a5760405162461bcd60e51b8152602060048201526006602482015265121054d7d4d360d21b604482015260640161050d565b50613604565b60018860038111156135645761356461576f565b14158061357657506000816101200151115b6135aa5760405162461bcd60e51b81526020600482015260056024820152641393d7d4d360da1b604482015260640161050d565b60008860038111156135be576135be61576f565b1415806135d057506000816101000151115b6136045760405162461bcd60e51b815260206004820152600560248201526404e4f5f54560dc1b604482015260640161050d565b60006040518060800160405280896001600160a01b031681526020018881526020018781526020018a600381111561363e5761363e61576f565b905260405163108c3d4960e11b81529091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906321187a929061368f908490600401615cac565b602060405180830381865afa1580156136ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136d091906155d7565b15806137645750604051633f1b72bf60e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063fc6dcafc90613723908490600401615cac565b602060405180830381865afa158015613740573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061376491906155d7565b15613e3957600060038a600381111561377f5761377f61576f565b036139bf57604051632e21e28b60e21b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b8878a2c906137d7908d908d908d906004016155ab565b6101a060405180830381865afa1580156137f5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061381991906155ff565b90508060c00151816060015161382f9190615ab2565b602082015160a0830151604051633f54af9960e11b81526000600482018190526024820193909352901515604482015260648101839052919350906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637ea95f32906084016040805180830381865afa1580156138ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138de9190615af5565b5090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166380f6cfc26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561393f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139639190615ac9565b60c08301516139729083615ab2565b11156139b85760405162461bcd60e51b81526020600482015260156024820152740a0a492868abe929aa08286a8bea89e9ebe90928e9605b1b604482015260640161050d565b5050613a85565b6402540be4008360e001517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638c8ff1d58c8c8c6040518463ffffffff1660e01b8152600401613a1a939291906155ab565b60c060405180830381865afa158015613a37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a5b9190615bc2565b602001518560600151613a6e9190615ab2565b613a789190615ab2565b613a829190615c42565b90505b604051633348540360e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636690a80690613ad59087908c9086906004016155ab565b600060405180830381600087803b158015613aef57600080fd5b505af1158015613b03573d6000803e3d6000fd5b5050505060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316633078fff56040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b8b9190615752565b905060006001600160a01b03821663fa8dd4988b60038f6003811115613bb357613bb361576f565b14613bbf576003613bc2565b60025b866040518463ffffffff1660e01b8152600401613be193929190615b56565b6020604051808303816000875af1158015613c00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c249190615ac9565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663817fa1a46040518060c00160405280896001600160a01b031681526020018b81526020018e6001600160a01b031681526020018d81526020018c81526020018f6003811115613ca257613ca261576f565b815250836040518363ffffffff1660e01b8152600401613cc3929190615cba565b600060405180830381600087803b158015613cdd57600080fd5b505af1158015613cf1573d6000803e3d6000fd5b505060405163b9e0336f60e01b8152600481018d9052602481018690526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116935063aa88fd2e925087918a9187169063b9e0336f90604401602060405180830381865afa158015613d6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d939190615ac9565b6040518463ffffffff1660e01b8152600401613db193929190615d1b565b600060405180830381600087803b158015613dcb57600080fd5b505af1158015613ddf573d6000803e3d6000fd5b50505050898b6001600160a01b0316876001600160a01b03167f6d87222414c5850caf1d385b1e080a771b505825b082a2162d0f4af5ffc86c0084604051613e2991815260200190565b60405180910390a4505050613efb565b6040516346ea285b60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906346ea285b90613e879084908790600401615d43565b600060405180830381600087803b158015613ea157600080fd5b505af1158015613eb5573d6000803e3d6000fd5b5050505086886001600160a01b0316846001600160a01b03167fde7da272dc52e28c3b33c5c74b461da89b05bd790d845e82db2f69bbf08108e760405160405180910390a45b505050505050505050565b613f0e614c7c565b613f16614c8a565b6000613f20610404565b604051636e6f99cd60e11b81529091506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063dcdf339a90613f73908490879087906004016155ab565b602060405180830381865afa158015613f90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fb491906155d7565b613feb5760405162461bcd60e51b81526020600482015260086024820152671393d7d31253525560c21b604482015260640161050d565b604051632e21e28b60e21b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b8878a2c9061403e908590889088906004016155ab565b6101a060405180830381865afa15801561405c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061408091906155ff565b905061408f8285856003614ccb565b60405163b4b0f56760e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b4b0f567906140df908590889088906004016155ab565b600060405180830381600087803b1580156140f957600080fd5b505af115801561410d573d6000803e3d6000fd5b50505050606081015160405163373873db60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830181905290851660248301526044820192909252636e70e7b690606401600060405180830381600087803b15801561418857600080fd5b505af115801561419c573d6000803e3d6000fd5b5050505083826001600160a01b03167ff1b38881d7f4b2b12141c5f39c5124545d6112532eb6afbe9630cdbde3ee53e9856040516141dc91815260200190565b60405180910390a350505050565b6141f2614c7c565b6141fa614c8a565b6000614204610404565b90506142138185856001614ccb565b6040516351d407ff60e11b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a3a80ffe90614266908590899089906004016155ab565b61014060405180830381865afa158015614284573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142a89190615ba5565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638c8ff1d58488886040518463ffffffff1660e01b81526004016142fc939291906155ab565b60c060405180830381865afa158015614319573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061433d9190615bc2565b905060008260e001511161437e5760405162461bcd60e51b81526020600482015260086024820152674e4f5f545241444560c01b604482015260640161050d565b60008260e001516064604b8560a001516143989190615ab2565b6143a29190615c42565b6143ac9190615c42565b90508415806143eb57508260c001516143d757808360a001516143cf9190615909565b8511156143eb565b808360a001516143e79190615ae2565b8510155b6144245760405162461bcd60e51b815260206004820152600a602482015269534c5f544f4f5f42494760b01b604482015260640161050d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316633078fff56040518163ffffffff1660e01b8152600401602060405180830381865afa158015614484573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144a89190615752565b90508515806145845750806001600160a01b03166335b03c176040518163ffffffff1660e01b8152600401602060405180830381865afa1580156144f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145149190615752565b6001600160a01b03166324abd3fb896040518263ffffffff1660e01b815260040161454191815260200190565b602060405180830381865afa15801561455e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061458291906155d7565b155b156147685760405163a354418160e01b81526001600160a01b038681166004830152602482018a905260448201899052606482018890527f0000000000000000000000000000000000000000000000000000000000000000169063a354418190608401600060405180830381600087803b15801561460157600080fd5b505af1158015614615573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031662b127836040518163ffffffff1660e01b8152600401602060405180830381865afa158015614676573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061469a9190615752565b6001600160a01b0316737ca99c35586739c7f14191a8a00f072ff804e4c76342b0a9619091878b8b60006146cc614e70565b6040518763ffffffff1660e01b81526004016146ed96959493929190615799565b60006040518083038186803b15801561470557600080fd5b505af4158015614719573d6000803e3d6000fd5b5050604080518a8152602081018a90528b93506001600160a01b03891692507f1fc4a6c7ffe506697979b8ed54dc4135cd1ecd26a2745f70b760a2492222b316910160405180910390a3614926565b6000816001600160a01b031663fa8dd4988a60046402540be4008960e0015189602001518b6060015161479b9190615ab2565b6147a59190615ab2565b6147af9190615c42565b6040518463ffffffff1660e01b81526004016147cd93929190615b56565b6020604051808303816000875af11580156147ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148109190615ac9565b6040805160c080820183526001600160a01b038a81168352602083018e81528385018e815260a0808d015160608701908152948d01511515608087019081529086018f81529651635c109dfd60e11b81526004810189905295518416602487015291516044860152516064850152915160848401529051151560a4830152915160c482015291925083169063b8213bfa9060e401600060405180830381600087803b1580156148be57600080fd5b505af11580156148d2573d6000803e3d6000fd5b5050505088866001600160a01b0316827ffdfffd671d06639f57ee329f42ea52018346eb90ed43679721e81cc12bfa10548b8b60405161491c929190918252602082015260400190565b60405180910390a4505b5050505050505050565b32331461496d5760405162461bcd60e51b815260206004820152600b60248201526a1393d7d0d3d395149050d560aa1b604482015260640161050d565b33600090815260208190526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b6149a4614c7c565b6149ac614c8a565b60006149b6610404565b90506149c58185856000614ccb565b6040516351d407ff60e11b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a3a80ffe90614a18908590899089906004016155ab565b61014060405180830381865afa158015614a36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a5a9190615ba5565b905060008160e0015111614a9b5760405162461bcd60e51b81526020600482015260086024820152674e4f5f545241444560c01b604482015260640161050d565b604051637fdb96f360e01b81526001600160a01b0383811660048301526024820187905260448201869052606482018590527f00000000000000000000000000000000000000000000000000000000000000001690637fdb96f390608401600060405180830381600087803b158015614b1357600080fd5b505af1158015614b27573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031662b127836040518163ffffffff1660e01b8152600401602060405180830381865afa158015614b88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614bac9190615752565b6001600160a01b0316737ca99c35586739c7f14191a8a00f072ff804e4c76369beb2c190918488886000614bde614e70565b6040518763ffffffff1660e01b8152600401614bff96959493929190615799565b60006040518083038186803b158015614c1757600080fd5b505af4158015614c2b573d6000803e3d6000fd5b505060408051878152602081018790528893506001600160a01b03861692507f7e06a81c7a47891ccc7455b5ccb2ed850e32bb655ccda67eb3ebaaeed83242a4910160405180910390a35050505050565b323314614c8857600080fd5b565b600454610100900460ff1615614c885760405162461bcd60e51b815260040161050d90602080825260049082015263444f4e4560e01b604082015260600190565b60006040518060800160405280866001600160a01b03168152602001858152602001848152602001836003811115614d0557614d0561576f565b905260405163108c3d4960e11b81529091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906321187a9290614d56908490600401615cac565b602060405180830381865afa158015614d73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614d9791906155d7565b1580614e2b5750604051633f1b72bf60e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063fc6dcafc90614dea908490600401615cac565b602060405180830381865afa158015614e07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614e2b91906155d7565b614e695760405162461bcd60e51b815260206004820152600f60248201526e2822a72224a723afaa2924a3a3a2a960891b604482015260640161050d565b5050505050565b600061a4b1461480614e84575062066eed46145b15614ef15760646001600160a01b031663a3b1b31d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015614ec8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614eec9190615ac9565b905090565b504390565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166312d43a516040518163ffffffff1660e01b8152600401602060405180830381865afa158015614f54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614f789190615752565b6001600160a01b0316336001600160a01b031614614c885760405162461bcd60e51b8152602060048201526008602482015267474f565f4f4e4c5960c01b604482015260640161050d565b60006002836003811115614fd957614fd961576f565b03614fe657506001615207565b6000614ff0614e70565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031662b127836040518163ffffffff1660e01b8152600401602060405180830381865afa158015615051573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906150759190615752565b9050600085600381111561508b5761508b61576f565b0361511f57604051632a0b3e7160e01b8152737ca99c35586739c7f14191a8a00f072ff804e4c790632a0b3e71906150d4906001600160a01b0385169088908790600401615d67565b602060405180830381865af41580156150f1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061511591906155d7565b1592505050615207565b60018560038111156151335761513361576f565b0361517c57604051634116cf5360e11b8152737ca99c35586739c7f14191a8a00f072ff804e4c79063822d9ea6906150d4906001600160a01b0385169088908790600401615d67565b60405163d76063d160e01b8152737ca99c35586739c7f14191a8a00f072ff804e4c79063d76063d1906151c0906001600160a01b0385169088908790600401615d67565b602060405180830381865af41580156151dd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061520191906155d7565b15925050505b92915050565b600080600080600060a0868803121561522557600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60006020828403121561525a57600080fd5b5035919050565b6001600160a01b038116811461527657600080fd5b50565b803561528481615261565b919050565b60008060006040848603121561529e57600080fd5b83356152a981615261565b9250602084013567ffffffffffffffff808211156152c657600080fd5b818601915086601f8301126152da57600080fd5b8135818111156152e957600080fd5b8760208285010111156152fb57600080fd5b6020830194508093505050509250925092565b60005b83811015615329578181015183820152602001615311565b50506000910152565b6000815180845261534a81602086016020860161530e565b601f01601f19169290920160200192915050565b6020815260006153716020830184615332565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051610140810167ffffffffffffffff811182821017156153b2576153b2615378565b60405290565b6040516101a0810167ffffffffffffffff811182821017156153b2576153b2615378565b801515811461527657600080fd5b8035615284816153dc565b80356003811061528457600080fd5b60008060008060008587036101c081121561541e57600080fd5b6101408082121561542e57600080fd5b61543661538e565b915061544188615279565b82526020880135602083015260408801356040830152606088013560608301526080880135608083015260a088013560a083015261548160c089016153ea565b60c083015260e088013560e08301526101008089013581840152506101208089013581840152508196506154b68189016153f5565b95505050610160860135925061018086013591506154d76101a08701615279565b90509295509295909350565b600080604083850312156154f657600080fd5b50508035926020909101359150565b60008060008060008060c0878903121561551e57600080fd5b86356004811061552d57600080fd5b9550602087013561553d81615261565b95989597505050506040840135936060810135936080820135935060a0909101359150565b60008060006060848603121561557757600080fd5b505081359360208301359350604090920135919050565b6000602082840312156155a057600080fd5b813561537181615261565b6001600160a01b039390931683526020830191909152604082015260600190565b8051615284816153dc565b6000602082840312156155e957600080fd5b8151615371816153dc565b805161528481615261565b60006101a0828403121561561257600080fd5b61561a6153b8565b615623836155f4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015261565960a084016155cc565b60a082015260c0838101519082015260e080840151908201526101008084015190820152610120808401519082015261014080840151908201526101608084015190820152610180928301519281019290925250919050565b81516001600160a01b031681526101a081016020830151602083015260408301516040830152606083015160608301526080830151608083015260a08301516156ff60a084018215159052565b5060c0838101519083015260e08084015190830152610100808401519083015261012080840151908301526101408084015190830152610160808401519083015261018092830151929091019190915290565b60006020828403121561576457600080fd5b815161537181615261565b634e487b7160e01b600052602160045260246000fd5b600281106157955761579561576f565b9052565b6001600160a01b03878116825286166020820152604081018590526060810184905260c081016157cc6080830185615785565b8260a0830152979650505050505050565b600061014082840312156157f057600080fd5b6157f861538e565b9050615803826155f4565b81526020820151602082015260408201516040820152606082015160608201526080820151608082015260a082015160a082015261584360c083016155cc565b60c082015260e082015160e082015261010080830151818301525061012080830151818301525092915050565b60006101e0828403121561588357600080fd5b60405160c0810181811067ffffffffffffffff821117156158a6576158a6615378565b6040526158b384846157dd565b81526101408301516020820152610160830151604082015261018083015160608201526101a083015160808201526101c09092015160a083015250919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115615207576152076158f3565b805180516001600160a01b031683526020810151602084015260408101516040840152606081015160608401526080810151608084015260a081015160a084015260c081015161597060c085018215159052565b5060e081810151908401526101008082015190840152610120908101519083015260208101516101408301526040810151610160830152606081015161018083015260808101516101a083015260a001516101c090910152565b6101e08101615207828461591c565b600082516159eb81846020870161530e565b9190910192915050565b8183823760009101908152919050565b600060208284031215615a1757600080fd5b815167ffffffffffffffff80821115615a2f57600080fd5b818401915084601f830112615a4357600080fd5b815181811115615a5557615a55615378565b604051601f8201601f19908116603f01168101908382118183101715615a7d57615a7d615378565b81604052828152876020848701011115615a9657600080fd5b615aa783602083016020880161530e565b979650505050505050565b8082028115828204841417615207576152076158f3565b600060208284031215615adb57600080fd5b5051919050565b81810381811115615207576152076158f3565b60008060408385031215615b0857600080fd5b505080516020909101519092909150565b6001600160a01b038516815260208101849052604081018390526080810160038310615b4757615b4761576f565b82606083015295945050505050565b8381526060810160058410615b6d57615b6d61576f565b602082019390935260400152919050565b6102208101615b8d828661591c565b836101e0830152821515610200830152949350505050565b60006101408284031215615bb857600080fd5b61537183836157dd565b600060c08284031215615bd457600080fd5b60405160c0810181811067ffffffffffffffff82111715615bf757615bf7615378565b8060405250825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a0830151615c36816153dc565b60a08201529392505050565b600082615c5f57634e487b7160e01b600052601260045260246000fd5b500490565b600481106157955761579561576f565b6001600160a01b03815116825260208101516020830152604081015160408301526060810151615ca76060840182615c64565b505050565b608081016152078284615c74565b600060e0820190506001600160a01b038085511683526020850151602084015280604086015116604084015250606084015160608301526080840151608083015260a0840151615d0d60a0840182615c64565b508260c08301529392505050565b60c08101615d298286615c74565b6001600160a01b0393909316608082015260a00152919050565b60a08101615d518285615c74565b6001600160a01b03831660808301529392505050565b600060c0820190506001600160a01b0380861683528085511660208401525060208401516040830152604084015160608301526060840151615dac6080840182615785565b508260a083015294935050505056fea2646970667358221220facbb2ac7710251165f9e6c004977cba5593ba7a4a952e0f526731d8b665c7f064736f6c63430008110033000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c000000000000000000000000de5750071caca8db173fc6543d23d0bcacacfec300000000000000000000000004a5e3cf21b0080b72facdca634349a56982d497000000000000000000000000aa379dd7ec0bae467490e89bb2055a7e01231b8f000000000000000000000000000000000000000000001a784379d99db42000000000000000000000000000000000000000000000000000000000000000000005

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061018e5760003560e01c80639a10cc32116100de578063b8ebd5cc11610097578063bffe348611610071578063bffe34861461038e578063ca5eb5e1146103b7578063d3dc7539146103ca578063d8defd15146103f157600080fd5b8063b8ebd5cc14610355578063b9b6573a14610368578063be73fb991461037b57600080fd5b80639a10cc32146102e75780639aa7c0e514610307578063a2a3c0cb1461031a578063ae8421e11461032d578063b187bd2614610335578063b81bfa051461034257600080fd5b8063410c0b7c1161014b578063876d3abd11610125578063876d3abd1461028c5780638f0622271461029f578063934d1cf4146102c1578063990382cf146102d457600080fd5b8063410c0b7c146102545780635ad9f9931461025d5780638456cb591461028457600080fd5b8063119df25f146101935780631346b0ff146101b857806316fff074146101df578063279a165c14610206578063318a368b1461021d57806336fb8b1514610232575b600080fd5b61019b610404565b6040516001600160a01b0390911681526020015b60405180910390f35b61019b7f00000000000000000000000004a5e3cf21b0080b72facdca634349a56982d49781565b61019b7f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c81565b61020f60025481565b6040519081526020016101af565b61023061022b36600461520d565b61042c565b005b61023033600090815260208190526040902080546001600160a01b0319169055565b61020f60035481565b61019b7f000000000000000000000000de5750071caca8db173fc6543d23d0bcacacfec381565b610230610861565b61023061029a366004615248565b6108b7565b6004546102b190610100900460ff1681565b60405190151581526020016101af565b6102306102cf366004615248565b610bb8565b6102306102e2366004615248565b610c59565b6102fa6102f5366004615289565b610fb7565b6040516101af919061535e565b610230610315366004615404565b6110fa565b6102306103283660046154e3565b6124ab565b610230612a4e565b6004546102b19060ff1681565b610230610350366004615248565b612aae565b610230610363366004615505565b612b52565b6102306103763660046154e3565b613f06565b610230610389366004615562565b6141ea565b61019b61039c36600461558e565b6000602081905290815260409020546001600160a01b031681565b6102306103c536600461558e565b614930565b61019b7f000000000000000000000000aa379dd7ec0bae467490e89bb2055a7e01231b8f81565b6102306103ff366004615562565b61499c565b6001546000906001600160a01b031661041c57503390565b506001546001600160a01b031690565b610434614c7c565b61043c614c8a565b6000610446610404565b604051636e6f99cd60e11b81529091506001600160a01b037f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c169063dcdf339a906104999084908a908a906004016155ab565b602060405180830381865afa1580156104b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104da91906155d7565b6105165760405162461bcd60e51b81526020600482015260086024820152671393d7d31253525560c21b60448201526064015b60405180910390fd5b604051632e21e28b60e21b81526000906001600160a01b037f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c169063b8878a2c906105699085908b908b906004016155ab565b6101a060405180830381865afa158015610587573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ab91906155ff565b90508315806105ca57508060a001516105c6578484106105ca565b8484115b6106015760405162461bcd60e51b8152602060048201526008602482015267057524f4e475f54560c41b604482015260640161050d565b82158061061e57508060a0015161061a5784831161061e565b8483105b6106555760405162461bcd60e51b815260206004820152600860248201526715d493d391d7d4d360c21b604482015260640161050d565b6106628288886003614ccb565b6101208101859052610140810185905260e081018490526101008101839052604051635bb3b04560e11b81526001600160a01b037f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c169063b767608a906106cd9084906004016156b2565b600060405180830381600087803b1580156106e757600080fd5b505af11580156106fb573d6000803e3d6000fd5b505050507f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b031662b127836040518163ffffffff1660e01b8152600401602060405180830381865afa15801561075c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107809190615752565b6001600160a01b0316737ca99c35586739c7f14191a8a00f072ff804e4c7634863c9c39091848a8a60016107b2614e70565b6040518763ffffffff1660e01b81526004016107d396959493929190615799565b60006040518083038186803b1580156107eb57600080fd5b505af41580156107ff573d6000803e3d6000fd5b50506040805189815260208101899052908101879052606081018690528992506001600160a01b03851691507f21e15d62c2ece17c1dc11c5fa45dcefdc6f99f199aa111d1363ff242f23e1c5c9060800160405180910390a350505050505050565b610869614ef6565b6004805460ff8082161560ff1990921682179092556040519116151581527f0e2fb031ee032dc02d8011dc50b816eb450cf856abd8261680dac74f72165bd2906020015b60405180910390a1565b6108bf614c7c565b6108c7614c8a565b60006108d1610404565b60405163b66e6b0560e01b8152600481018490529091506000906001600160a01b037f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c169063b66e6b05906024016101e060405180830381865afa15801561093d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109619190615870565b80516020820151919250901580159061098b575060035482602001516109879190615909565b4310155b6109c65760405162461bcd60e51b815260206004820152600c60248201526b15d0525517d512535153d55560a21b604482015260640161050d565b826001600160a01b031681600001516001600160a01b031614610a1c5760405162461bcd60e51b815260206004820152600e60248201526d2727aa2faca7aaa92fa7a92222a960911b604482015260640161050d565b60008160e0015111610a6a5760405162461bcd60e51b815260206004820152601760248201527657524f4e475f4d41524b45545f4f524445525f5459504560481b604482015260640161050d565b604051630195728b60e71b815260048101859052600160248201527f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b03169063cab9458090604401600060405180830381600087803b158015610ad357600080fd5b505af1158015610ae7573d6000803e3d6000fd5b50505050608081015160405163373873db60e11b81526001600160a01b037f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c81166004830181905290861660248301526044820192909252636e70e7b690606401600060405180830381600087803b158015610b6257600080fd5b505af1158015610b76573d6000803e3d6000fd5b50505050837f3adaa586cdbe84dd24e45bd7dada6da933d7c2d1c7b4e4cd02fce033356decb183604051610baa91906159ca565b60405180910390a250505050565b610bc0614ef6565b60008111610bfa5760405162461bcd60e51b8152602060048201526007602482015266056414c55455f360cc1b604482015260640161050d565b600281905560408051818152600991810191909152686d6178506f7344616960b81b6060820152602081018290527f8cf3e35f6221b16e1670a3413180c9484bf5aa71787905909fa82a6a2662e9ab906080015b60405180910390a150565b610c61614c7c565b610c69614c8a565b6000610c73610404565b60405163b66e6b0560e01b8152600481018490529091506000906001600160a01b037f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c169063b66e6b05906024016101e060405180830381865afa158015610cdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d039190615870565b805160208201519192509015801590610d2d57506003548260200151610d299190615909565b4310155b610d685760405162461bcd60e51b815260206004820152600c60248201526b15d0525517d512535153d55560a21b604482015260640161050d565b826001600160a01b031681600001516001600160a01b031614610dbe5760405162461bcd60e51b815260206004820152600e60248201526d2727aa2faca7aaa92fa7a92222a960911b604482015260640161050d565b60e081015115610e0a5760405162461bcd60e51b815260206004820152601760248201527657524f4e475f4d41524b45545f4f524445525f5459504560481b604482015260640161050d565b604051630195728b60e71b815260048101859052600060248201527f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b03169063cab9458090604401600060405180830381600087803b158015610e7357600080fd5b505af1158015610e87573d6000803e3d6000fd5b505050602082015160408084015190516024810192909252604482015260009150309060640160408051601f198184030181529181526020820180516001600160e01b031663a2a3c0cb60e01b17905251610ee291906159d9565b600060405180830381855af49150503d8060008114610f1d576040519150601f19603f3d011682016040523d82523d6000602084013e610f22565b606091505b5050905080610f78578160200151846001600160a01b03167f60e497734ddabcd7293fd91739aaf65cf525eb539c97be528125a235a89288d88460400151604051610f6f91815260200190565b60405180910390a35b847f3adaa586cdbe84dd24e45bd7dada6da933d7c2d1c7b4e4cd02fce033356decb184604051610fa891906159ca565b60405180910390a25050505050565b6001600160a01b038381166000908152602081905260409020546060911633146110235760405162461bcd60e51b815260206004820152601560248201527f44454c45474154455f4e4f545f415050524f5645440000000000000000000000604482015260640161050d565b600180546001600160a01b0319166001600160a01b0386161790556040516000908190309061105590879087906159f5565b600060405180830381855af49150503d8060008114611090576040519150601f19603f3d011682016040523d82523d6000602084013e611095565b606091505b5091509150816110e1576044815110156110ae57600080fd5b600481019050808060200190518101906110c89190615a05565b60405162461bcd60e51b815260040161050d919061535e565b600180546001600160a01b031916905595945050505050565b611102614c7c565b61110a614c8a565b60045460ff16156111465760405162461bcd60e51b815260206004820152600660248201526514105554d15160d21b604482015260640161050d565b600019828660a001516111599190615ab2565b106111915760405162461bcd60e51b81526020600482015260086024820152674f564552464c4f5760c01b604482015260640161050d565b60007f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b0316633078fff56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112159190615752565b90506000816001600160a01b03166335b03c176040518163ffffffff1660e01b8152600401602060405180830381865afa158015611257573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127b9190615752565b90506000611287610404565b90507f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b031663f65d9dbe6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130b9190615ac9565b6020890151604051634bf3ccad60e11b81526001600160a01b03848116600483015260248201929092527f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c909116906397e7995a90604401602060405180830381865afa158015611380573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a49190615ac9565b60208a0151604051639c8912f160e01b81526001600160a01b03858116600483015260248201929092527f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c90911690639c8912f190604401602060405180830381865afa158015611419573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061143d9190615ac9565b60208b01516040516307218dad60e21b81526001600160a01b03868116600483015260248201929092527f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c90911690631c8636b490604401602060405180830381865afa1580156114b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d69190615ac9565b6114e09190615909565b6114ea9190615909565b1061152d5760405162461bcd60e51b815260206004820152601360248201527226a0ac2faa2920a222a9afa822a92fa820a4a960691b604482015260640161050d565b7f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b0316638049fde76040518163ffffffff1660e01b8152600401602060405180830381865afa15801561158b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115af9190615ac9565b60405163f7b3c6fd60e01b81526001600160a01b0383811660048301527f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c169063f7b3c6fd90602401602060405180830381865afa158015611615573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116399190615ac9565b1061167b5760405162461bcd60e51b81526020600482015260126024820152714d41585f50454e44494e475f4f524445525360701b604482015260640161050d565b600254886080015111156116c15760405162461bcd60e51b815260206004820152600d60248201526c41424f56455f4d41585f504f5360981b604482015260640161050d565b602088015160405163066c581160e11b815260048101919091526001600160a01b03831690630cd8b02290602401602060405180830381865afa15801561170c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117309190615ac9565b8860e0015189608001516117449190615ab2565b10156117825760405162461bcd60e51b815260206004820152600d60248201526c42454c4f575f4d494e5f504f5360981b604482015260640161050d565b60008860e001511180156118085750602088015160405163059a992d60e41b815260048101919091526001600160a01b038316906359a992d090602401602060405180830381865afa1580156117dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118009190615ac9565b8860e0015110155b801561188657506020880151604051630a06da4f60e21b815260048101919091526001600160a01b0383169063281b693c90602401602060405180830381865afa15801561185a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061187e9190615ac9565b8860e0015111155b6118c75760405162461bcd60e51b815260206004820152601260248201527113115591549051d157d25390d3d4949150d560721b604482015260640161050d565b8515806119d8575060006001600160a01b037f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c1663265aa62161190b60018a615ae2565b6040518263ffffffff1660e01b815260040161192991815260200190565b602060405180830381865afa158015611946573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061196a9190615752565b6040516370a0823160e01b81526001600160a01b03848116600483015291909116906370a0823190602401602060405180830381865afa1580156119b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119d69190615ac9565b115b611a325760405162461bcd60e51b815260206004820152602560248201527f4e4f5f434f52524553504f4e44494e475f4e46545f5350524541445f5245445560448201526421aa24a7a760d91b606482015260840161050d565b6101008801511580611a6657508760c00151611a59578760a0015188610100015110611a66565b8760a00151886101000151115b611a9d5760405162461bcd60e51b8152602060048201526008602482015267057524f4e475f54560c41b604482015260640161050d565b6101208801511580611ad157508760c00151611ac4578760a0015188610120015111611ad1565b8760a00151886101200151105b611b085760405162461bcd60e51b815260206004820152600860248201526715d493d391d7d4d360c21b604482015260640161050d565b60007f00000000000000000000000004a5e3cf21b0080b72facdca634349a56982d4976001600160a01b0316637ea95f3260008b602001518c60c001518d60e001518e60800151611b599190615ab2565b6040516001600160e01b031960e087901b168152600481019490945260248401929092521515604483015260648201526084016040805180830381865afa158015611ba8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bcc9190615af5565b5090507f00000000000000000000000004a5e3cf21b0080b72facdca634349a56982d4976001600160a01b03166380f6cfc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c519190615ac9565b60e08a0151611c609083615ab2565b1115611ca65760405162461bcd60e51b81526020600482015260156024820152740a0a492868abe929aa08286a8bea89e9ebe90928e9605b1b604482015260640161050d565b608089015160405163373873db60e11b81526001600160a01b0384811660048301527f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c16602482018190526044820192909252636e70e7b690606401600060405180830381600087803b158015611d1c57600080fd5b505af1158015611d30573d6000803e3d6000fd5b5060009250611d3d915050565b886002811115611d4f57611d4f61576f565b1461217757602089015160405163226a27ad60e11b81526001600160a01b03848116600483015260248201929092526000917f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c16906344d44f5a90604401602060405180830381865afa158015611dca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dee9190615ac9565b90507f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b031663d3b5fe70604051806101a00160405280866001600160a01b031681526020018d6020015181526020018481526020018d60800151815260200160008c11611e63576000611efc565b6001600160a01b037f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c16633dae10a0611e9d60018f615ae2565b6040518263ffffffff1660e01b8152600401611ebb91815260200190565b602060405180830381865afa158015611ed8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611efc9190615ac9565b81526020018d60c00151151581526020018d60e0015181526020018d610100015181526020018d610120015181526020018d60a0015181526020018d60a00151815260200143815260200160008152506040518263ffffffff1660e01b8152600401611f6891906156b2565b600060405180830381600087803b158015611f8257600080fd5b505af1158015611f96573d6000803e3d6000fd5b5050505060208a0151604051630ec5706160e41b81527f000000000000000000000000de5750071caca8db173fc6543d23d0bcacacfec36001600160a01b03169163ec57061091611fef91879186908f90600401615b19565b600060405180830381600087803b15801561200957600080fd5b505af115801561201d573d6000803e3d6000fd5b505050507f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b031662b127836040518163ffffffff1660e01b8152600401602060405180830381865afa15801561207e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120a29190615752565b6001600160a01b0316737ca99c35586739c7f14191a8a00f072ff804e4c7634863c9c39091858d602001518560016120d8614e70565b6040518763ffffffff1660e01b81526004016120f996959493929190615799565b60006040518083038186803b15801561211157600080fd5b505af4158015612125573d6000803e3d6000fd5b505050508960200151836001600160a01b03167fdfabd6f206f17b7f2e1f9e0d33c40d30d1e8d7b6a4f520a03fdc1c18110593438360405161216991815260200190565b60405180910390a35061241d565b6000846001600160a01b031663fa8dd4988b6020015160008d60e001518e608001516121a39190615ab2565b6040518463ffffffff1660e01b81526004016121c193929190615b56565b6020604051808303816000875af11580156121e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122049190615ac9565b90507f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b031663c76faf786040518060c00160405280604051806101400160405280886001600160a01b031681526020018f60200151815260200160008152602001600081526020018f608001518152602001600081526020018f60c00151151581526020018f60e0015181526020018f610100015181526020018f61012001518152508152602001600081526020018d60a0015181526020018a815260200160008c116122d9576000612372565b6001600160a01b037f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c16633dae10a061231360018f615ae2565b6040518263ffffffff1660e01b815260040161233191815260200190565b602060405180830381865afa15801561234e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123729190615ac9565b815260200160008152508360016040518463ffffffff1660e01b815260040161239d93929190615b7e565b600060405180830381600087803b1580156123b757600080fd5b505af11580156123cb573d6000803e3d6000fd5b505050508960200151836001600160a01b0316827f3e544118c04e3bb18b669475695cd270ba0e41fb13177483f01c14222de62a866001604051612413911515815260200190565b60405180910390a4505b6040516326e2ada160e21b81526001600160a01b03838116600483015286811660248301527f000000000000000000000000aa379dd7ec0bae467490e89bb2055a7e01231b8f1690639b8ab68490604401600060405180830381600087803b15801561248857600080fd5b505af115801561249c573d6000803e3d6000fd5b50505050505050505050505050565b6124b3614c7c565b6124bb614c8a565b60006124c5610404565b905060007f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b031663a3a80ffe8386866040518463ffffffff1660e01b8152600401612519939291906155ab565b61014060405180830381865afa158015612537573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061255b9190615ba5565b905060007f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b0316638c8ff1d58487876040518463ffffffff1660e01b81526004016125af939291906155ab565b60c060405180830381865afa1580156125cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f09190615bc2565b90507f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b0316638049fde76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612650573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126749190615ac9565b60405163f7b3c6fd60e01b81526001600160a01b0385811660048301527f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c169063f7b3c6fd90602401602060405180830381865afa1580156126da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fe9190615ac9565b106127405760405162461bcd60e51b81526020600482015260126024820152714d41585f50454e44494e475f4f524445525360701b604482015260640161050d565b8060a00151156127895760405162461bcd60e51b81526020600482015260146024820152731053149150511657d091525391d7d0d313d4d15160621b604482015260640161050d565b60008260e00151116127c85760405162461bcd60e51b81526020600482015260086024820152674e4f5f545241444560c01b604482015260640161050d565b60007f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b0316633078fff56040518163ffffffff1660e01b8152600401602060405180830381865afa158015612828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061284c9190615752565b6001600160a01b031663fa8dd4988760016402540be4008760e001518760200151896060015161287c9190615ab2565b6128869190615ab2565b6128909190615c42565b6040518463ffffffff1660e01b81526004016128ae93929190615b56565b6020604051808303816000875af11580156128cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128f19190615ac9565b90507f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b031663c76faf786040518060c00160405280604051806101400160405280896001600160a01b031681526020018b81526020018a81526020016000815260200160008152602001600081526020016000151581526020016000815260200160008152602001600081525081526020016000815260200160008152602001600081526020016000815260200160008152508360006040518463ffffffff1660e01b81526004016129cc93929190615b7e565b600060405180830381600087803b1580156129e657600080fd5b505af11580156129fa573d6000803e3d6000fd5b5050505085846001600160a01b0316827f3e544118c04e3bb18b669475695cd270ba0e41fb13177483f01c14222de62a866000604051612a3e911515815260200190565b60405180910390a4505050505050565b612a56614ef6565b6004805460ff610100808304821615810261ff001990931692909217928390556040517fc3a6f986261de9467c2838c6df8ef74f9107855159205600c0bc7a14cdfd3888936108ad9390049091161515815260200190565b612ab6614ef6565b60008111612af05760405162461bcd60e51b8152602060048201526007602482015266056414c55455f360cc1b604482015260640161050d565b600381905560408051818152601391810191909152721b585c9ad95d13dc99195c9cd51a5b595bdd5d606a1b6060820152602081018290527f8cf3e35f6221b16e1670a3413180c9484bf5aa71787905909fa82a6a2662e9ab90608001610c4e565b612b5a614c7c565b612b62614c8a565b6000612b6c610404565b905060018210158015612b80575060058211155b612bbd5760405162461bcd60e51b815260206004820152600e60248201526d57524f4e475f4e46545f5459504560901b604482015260640161050d565b6001600160a01b03808216907f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c1663265aa621612bfb600186615ae2565b6040518263ffffffff1660e01b8152600401612c1991815260200190565b602060405180830381865afa158015612c36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5a9190615752565b6001600160a01b0316636352211e856040518263ffffffff1660e01b8152600401612c8791815260200190565b602060405180830381865afa158015612ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cc89190615752565b6001600160a01b031614612d075760405162461bcd60e51b81526020600482015260066024820152651393d7d3919560d21b604482015260640161050d565b7f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b031663f8d24b486040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d899190615ac9565b60405163aa3b7d7760e01b8152600481018590527f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b03169063aa3b7d7790602401602060405180830381865afa158015612dee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e129190615ac9565b612e1c9190615909565b431015612e5e5760405162461bcd60e51b815260206004820152601060248201526f535543434553535f54494d454c4f434b60801b604482015260640161050d565b612ed3876040518060800160405280896001600160a01b03168152602001888152602001878152602001600380811115612e9a57612e9a61576f565b8b6003811115612eac57612eac61576f565b14612eb8576000612ebb565b60015b6001811115612ecc57612ecc61576f565b9052614fc3565b612f0c5760405162461bcd60e51b815260206004820152600a602482015269125397d512535153d55560b21b604482015260640161050d565b60405162c1932360e11b81524360048201526001600160a01b0382811660248301526044820185905287811660648301526084820187905260a4820186905260009182917f000000000000000000000000de5750071caca8db173fc6543d23d0bcacacfec3169063018326469060c4016040805180830381865afa158015612f98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fbc9190615af5565b60405163255b694560e21b8152600481018390526024810182905291935091507f000000000000000000000000de5750071caca8db173fc6543d23d0bcacacfec36001600160a01b03169063956da51490604401602060405180830381865afa15801561302d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061305191906155d7565b1561308b5760405162461bcd60e51b815260206004820152600a602482015269424f545f494e5f55534560b01b604482015260640161050d565b604051630580c65760e41b815260048101839052602481018290527f000000000000000000000000de5750071caca8db173fc6543d23d0bcacacfec36001600160a01b03169063580c657090604401600060405180830381600087803b1580156130f457600080fd5b505af1158015613108573d6000803e3d6000fd5b50505050505061316f60405180610140016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160008152602001600081525090565b60038860038111156131835761318361576f565b0361325557604051636e6f99cd60e11b81526001600160a01b037f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c169063dcdf339a906131d8908a908a908a906004016155ab565b602060405180830381865afa1580156131f5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061321991906155d7565b6132505760405162461bcd60e51b81526020600482015260086024820152671393d7d31253525560c21b604482015260640161050d565b613604565b6040516351d407ff60e11b81526001600160a01b037f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c169063a3a80ffe906132a5908a908a908a906004016155ab565b61014060405180830381865afa1580156132c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132e79190615ba5565b905060008160e00151116133285760405162461bcd60e51b81526020600482015260086024820152674e4f5f545241444560c01b604482015260640161050d565b600288600381111561333c5761333c61576f565b036135505760007f00000000000000000000000004a5e3cf21b0080b72facdca634349a56982d4976001600160a01b0316636bc84d598360000151846020015185604001518660a001518760c001516402540be4007f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b0316638c8ff1d58b600001518c602001518d604001516040518463ffffffff1660e01b81526004016133ed939291906155ab565b60c060405180830381865afa15801561340a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342e9190615bc2565b602001518a606001516134419190615ab2565b61344b9190615c42565b60e08a8101516040519189901b6001600160e01b03191682526001600160a01b039790971660048201526024810195909552604485019390935260648401919091521515608483015260a482015260c481019190915260e401602060405180830381865afa1580156134c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134e59190615ac9565b90508161012001516000148061351557508160c0015161350c578161012001518110613515565b81610120015181115b61354a5760405162461bcd60e51b8152602060048201526006602482015265121054d7d4d360d21b604482015260640161050d565b50613604565b60018860038111156135645761356461576f565b14158061357657506000816101200151115b6135aa5760405162461bcd60e51b81526020600482015260056024820152641393d7d4d360da1b604482015260640161050d565b60008860038111156135be576135be61576f565b1415806135d057506000816101000151115b6136045760405162461bcd60e51b815260206004820152600560248201526404e4f5f54560dc1b604482015260640161050d565b60006040518060800160405280896001600160a01b031681526020018881526020018781526020018a600381111561363e5761363e61576f565b905260405163108c3d4960e11b81529091506001600160a01b037f000000000000000000000000de5750071caca8db173fc6543d23d0bcacacfec316906321187a929061368f908490600401615cac565b602060405180830381865afa1580156136ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136d091906155d7565b15806137645750604051633f1b72bf60e21b81526001600160a01b037f000000000000000000000000de5750071caca8db173fc6543d23d0bcacacfec3169063fc6dcafc90613723908490600401615cac565b602060405180830381865afa158015613740573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061376491906155d7565b15613e3957600060038a600381111561377f5761377f61576f565b036139bf57604051632e21e28b60e21b81526000906001600160a01b037f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c169063b8878a2c906137d7908d908d908d906004016155ab565b6101a060405180830381865afa1580156137f5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061381991906155ff565b90508060c00151816060015161382f9190615ab2565b602082015160a0830151604051633f54af9960e11b81526000600482018190526024820193909352901515604482015260648101839052919350906001600160a01b037f00000000000000000000000004a5e3cf21b0080b72facdca634349a56982d4971690637ea95f32906084016040805180830381865afa1580156138ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138de9190615af5565b5090507f00000000000000000000000004a5e3cf21b0080b72facdca634349a56982d4976001600160a01b03166380f6cfc26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561393f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139639190615ac9565b60c08301516139729083615ab2565b11156139b85760405162461bcd60e51b81526020600482015260156024820152740a0a492868abe929aa08286a8bea89e9ebe90928e9605b1b604482015260640161050d565b5050613a85565b6402540be4008360e001517f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b0316638c8ff1d58c8c8c6040518463ffffffff1660e01b8152600401613a1a939291906155ab565b60c060405180830381865afa158015613a37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a5b9190615bc2565b602001518560600151613a6e9190615ab2565b613a789190615ab2565b613a829190615c42565b90505b604051633348540360e11b81526001600160a01b037f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c1690636690a80690613ad59087908c9086906004016155ab565b600060405180830381600087803b158015613aef57600080fd5b505af1158015613b03573d6000803e3d6000fd5b5050505060007f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b0316633078fff56040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b8b9190615752565b905060006001600160a01b03821663fa8dd4988b60038f6003811115613bb357613bb361576f565b14613bbf576003613bc2565b60025b866040518463ffffffff1660e01b8152600401613be193929190615b56565b6020604051808303816000875af1158015613c00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c249190615ac9565b90507f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b031663817fa1a46040518060c00160405280896001600160a01b031681526020018b81526020018e6001600160a01b031681526020018d81526020018c81526020018f6003811115613ca257613ca261576f565b815250836040518363ffffffff1660e01b8152600401613cc3929190615cba565b600060405180830381600087803b158015613cdd57600080fd5b505af1158015613cf1573d6000803e3d6000fd5b505060405163b9e0336f60e01b8152600481018d9052602481018690526001600160a01b037f000000000000000000000000de5750071caca8db173fc6543d23d0bcacacfec38116935063aa88fd2e925087918a9187169063b9e0336f90604401602060405180830381865afa158015613d6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d939190615ac9565b6040518463ffffffff1660e01b8152600401613db193929190615d1b565b600060405180830381600087803b158015613dcb57600080fd5b505af1158015613ddf573d6000803e3d6000fd5b50505050898b6001600160a01b0316876001600160a01b03167f6d87222414c5850caf1d385b1e080a771b505825b082a2162d0f4af5ffc86c0084604051613e2991815260200190565b60405180910390a4505050613efb565b6040516346ea285b60e01b81526001600160a01b037f000000000000000000000000de5750071caca8db173fc6543d23d0bcacacfec316906346ea285b90613e879084908790600401615d43565b600060405180830381600087803b158015613ea157600080fd5b505af1158015613eb5573d6000803e3d6000fd5b5050505086886001600160a01b0316846001600160a01b03167fde7da272dc52e28c3b33c5c74b461da89b05bd790d845e82db2f69bbf08108e760405160405180910390a45b505050505050505050565b613f0e614c7c565b613f16614c8a565b6000613f20610404565b604051636e6f99cd60e11b81529091506001600160a01b037f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c169063dcdf339a90613f73908490879087906004016155ab565b602060405180830381865afa158015613f90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fb491906155d7565b613feb5760405162461bcd60e51b81526020600482015260086024820152671393d7d31253525560c21b604482015260640161050d565b604051632e21e28b60e21b81526000906001600160a01b037f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c169063b8878a2c9061403e908590889088906004016155ab565b6101a060405180830381865afa15801561405c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061408091906155ff565b905061408f8285856003614ccb565b60405163b4b0f56760e01b81526001600160a01b037f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c169063b4b0f567906140df908590889088906004016155ab565b600060405180830381600087803b1580156140f957600080fd5b505af115801561410d573d6000803e3d6000fd5b50505050606081015160405163373873db60e11b81526001600160a01b037f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c81166004830181905290851660248301526044820192909252636e70e7b690606401600060405180830381600087803b15801561418857600080fd5b505af115801561419c573d6000803e3d6000fd5b5050505083826001600160a01b03167ff1b38881d7f4b2b12141c5f39c5124545d6112532eb6afbe9630cdbde3ee53e9856040516141dc91815260200190565b60405180910390a350505050565b6141f2614c7c565b6141fa614c8a565b6000614204610404565b90506142138185856001614ccb565b6040516351d407ff60e11b81526000906001600160a01b037f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c169063a3a80ffe90614266908590899089906004016155ab565b61014060405180830381865afa158015614284573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142a89190615ba5565b905060007f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b0316638c8ff1d58488886040518463ffffffff1660e01b81526004016142fc939291906155ab565b60c060405180830381865afa158015614319573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061433d9190615bc2565b905060008260e001511161437e5760405162461bcd60e51b81526020600482015260086024820152674e4f5f545241444560c01b604482015260640161050d565b60008260e001516064604b8560a001516143989190615ab2565b6143a29190615c42565b6143ac9190615c42565b90508415806143eb57508260c001516143d757808360a001516143cf9190615909565b8511156143eb565b808360a001516143e79190615ae2565b8510155b6144245760405162461bcd60e51b815260206004820152600a602482015269534c5f544f4f5f42494760b01b604482015260640161050d565b60007f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b0316633078fff56040518163ffffffff1660e01b8152600401602060405180830381865afa158015614484573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144a89190615752565b90508515806145845750806001600160a01b03166335b03c176040518163ffffffff1660e01b8152600401602060405180830381865afa1580156144f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145149190615752565b6001600160a01b03166324abd3fb896040518263ffffffff1660e01b815260040161454191815260200190565b602060405180830381865afa15801561455e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061458291906155d7565b155b156147685760405163a354418160e01b81526001600160a01b038681166004830152602482018a905260448201899052606482018890527f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c169063a354418190608401600060405180830381600087803b15801561460157600080fd5b505af1158015614615573d6000803e3d6000fd5b505050507f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b031662b127836040518163ffffffff1660e01b8152600401602060405180830381865afa158015614676573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061469a9190615752565b6001600160a01b0316737ca99c35586739c7f14191a8a00f072ff804e4c76342b0a9619091878b8b60006146cc614e70565b6040518763ffffffff1660e01b81526004016146ed96959493929190615799565b60006040518083038186803b15801561470557600080fd5b505af4158015614719573d6000803e3d6000fd5b5050604080518a8152602081018a90528b93506001600160a01b03891692507f1fc4a6c7ffe506697979b8ed54dc4135cd1ecd26a2745f70b760a2492222b316910160405180910390a3614926565b6000816001600160a01b031663fa8dd4988a60046402540be4008960e0015189602001518b6060015161479b9190615ab2565b6147a59190615ab2565b6147af9190615c42565b6040518463ffffffff1660e01b81526004016147cd93929190615b56565b6020604051808303816000875af11580156147ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148109190615ac9565b6040805160c080820183526001600160a01b038a81168352602083018e81528385018e815260a0808d015160608701908152948d01511515608087019081529086018f81529651635c109dfd60e11b81526004810189905295518416602487015291516044860152516064850152915160848401529051151560a4830152915160c482015291925083169063b8213bfa9060e401600060405180830381600087803b1580156148be57600080fd5b505af11580156148d2573d6000803e3d6000fd5b5050505088866001600160a01b0316827ffdfffd671d06639f57ee329f42ea52018346eb90ed43679721e81cc12bfa10548b8b60405161491c929190918252602082015260400190565b60405180910390a4505b5050505050505050565b32331461496d5760405162461bcd60e51b815260206004820152600b60248201526a1393d7d0d3d395149050d560aa1b604482015260640161050d565b33600090815260208190526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b6149a4614c7c565b6149ac614c8a565b60006149b6610404565b90506149c58185856000614ccb565b6040516351d407ff60e11b81526000906001600160a01b037f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c169063a3a80ffe90614a18908590899089906004016155ab565b61014060405180830381865afa158015614a36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a5a9190615ba5565b905060008160e0015111614a9b5760405162461bcd60e51b81526020600482015260086024820152674e4f5f545241444560c01b604482015260640161050d565b604051637fdb96f360e01b81526001600160a01b0383811660048301526024820187905260448201869052606482018590527f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c1690637fdb96f390608401600060405180830381600087803b158015614b1357600080fd5b505af1158015614b27573d6000803e3d6000fd5b505050507f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b031662b127836040518163ffffffff1660e01b8152600401602060405180830381865afa158015614b88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614bac9190615752565b6001600160a01b0316737ca99c35586739c7f14191a8a00f072ff804e4c76369beb2c190918488886000614bde614e70565b6040518763ffffffff1660e01b8152600401614bff96959493929190615799565b60006040518083038186803b158015614c1757600080fd5b505af4158015614c2b573d6000803e3d6000fd5b505060408051878152602081018790528893506001600160a01b03861692507f7e06a81c7a47891ccc7455b5ccb2ed850e32bb655ccda67eb3ebaaeed83242a4910160405180910390a35050505050565b323314614c8857600080fd5b565b600454610100900460ff1615614c885760405162461bcd60e51b815260040161050d90602080825260049082015263444f4e4560e01b604082015260600190565b60006040518060800160405280866001600160a01b03168152602001858152602001848152602001836003811115614d0557614d0561576f565b905260405163108c3d4960e11b81529091506001600160a01b037f000000000000000000000000de5750071caca8db173fc6543d23d0bcacacfec316906321187a9290614d56908490600401615cac565b602060405180830381865afa158015614d73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614d9791906155d7565b1580614e2b5750604051633f1b72bf60e21b81526001600160a01b037f000000000000000000000000de5750071caca8db173fc6543d23d0bcacacfec3169063fc6dcafc90614dea908490600401615cac565b602060405180830381865afa158015614e07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614e2b91906155d7565b614e695760405162461bcd60e51b815260206004820152600f60248201526e2822a72224a723afaa2924a3a3a2a960891b604482015260640161050d565b5050505050565b600061a4b1461480614e84575062066eed46145b15614ef15760646001600160a01b031663a3b1b31d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015614ec8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614eec9190615ac9565b905090565b504390565b7f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b03166312d43a516040518163ffffffff1660e01b8152600401602060405180830381865afa158015614f54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614f789190615752565b6001600160a01b0316336001600160a01b031614614c885760405162461bcd60e51b8152602060048201526008602482015267474f565f4f4e4c5960c01b604482015260640161050d565b60006002836003811115614fd957614fd961576f565b03614fe657506001615207565b6000614ff0614e70565b905060007f000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c6001600160a01b031662b127836040518163ffffffff1660e01b8152600401602060405180830381865afa158015615051573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906150759190615752565b9050600085600381111561508b5761508b61576f565b0361511f57604051632a0b3e7160e01b8152737ca99c35586739c7f14191a8a00f072ff804e4c790632a0b3e71906150d4906001600160a01b0385169088908790600401615d67565b602060405180830381865af41580156150f1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061511591906155d7565b1592505050615207565b60018560038111156151335761513361576f565b0361517c57604051634116cf5360e11b8152737ca99c35586739c7f14191a8a00f072ff804e4c79063822d9ea6906150d4906001600160a01b0385169088908790600401615d67565b60405163d76063d160e01b8152737ca99c35586739c7f14191a8a00f072ff804e4c79063d76063d1906151c0906001600160a01b0385169088908790600401615d67565b602060405180830381865af41580156151dd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061520191906155d7565b15925050505b92915050565b600080600080600060a0868803121561522557600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60006020828403121561525a57600080fd5b5035919050565b6001600160a01b038116811461527657600080fd5b50565b803561528481615261565b919050565b60008060006040848603121561529e57600080fd5b83356152a981615261565b9250602084013567ffffffffffffffff808211156152c657600080fd5b818601915086601f8301126152da57600080fd5b8135818111156152e957600080fd5b8760208285010111156152fb57600080fd5b6020830194508093505050509250925092565b60005b83811015615329578181015183820152602001615311565b50506000910152565b6000815180845261534a81602086016020860161530e565b601f01601f19169290920160200192915050565b6020815260006153716020830184615332565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051610140810167ffffffffffffffff811182821017156153b2576153b2615378565b60405290565b6040516101a0810167ffffffffffffffff811182821017156153b2576153b2615378565b801515811461527657600080fd5b8035615284816153dc565b80356003811061528457600080fd5b60008060008060008587036101c081121561541e57600080fd5b6101408082121561542e57600080fd5b61543661538e565b915061544188615279565b82526020880135602083015260408801356040830152606088013560608301526080880135608083015260a088013560a083015261548160c089016153ea565b60c083015260e088013560e08301526101008089013581840152506101208089013581840152508196506154b68189016153f5565b95505050610160860135925061018086013591506154d76101a08701615279565b90509295509295909350565b600080604083850312156154f657600080fd5b50508035926020909101359150565b60008060008060008060c0878903121561551e57600080fd5b86356004811061552d57600080fd5b9550602087013561553d81615261565b95989597505050506040840135936060810135936080820135935060a0909101359150565b60008060006060848603121561557757600080fd5b505081359360208301359350604090920135919050565b6000602082840312156155a057600080fd5b813561537181615261565b6001600160a01b039390931683526020830191909152604082015260600190565b8051615284816153dc565b6000602082840312156155e957600080fd5b8151615371816153dc565b805161528481615261565b60006101a0828403121561561257600080fd5b61561a6153b8565b615623836155f4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015261565960a084016155cc565b60a082015260c0838101519082015260e080840151908201526101008084015190820152610120808401519082015261014080840151908201526101608084015190820152610180928301519281019290925250919050565b81516001600160a01b031681526101a081016020830151602083015260408301516040830152606083015160608301526080830151608083015260a08301516156ff60a084018215159052565b5060c0838101519083015260e08084015190830152610100808401519083015261012080840151908301526101408084015190830152610160808401519083015261018092830151929091019190915290565b60006020828403121561576457600080fd5b815161537181615261565b634e487b7160e01b600052602160045260246000fd5b600281106157955761579561576f565b9052565b6001600160a01b03878116825286166020820152604081018590526060810184905260c081016157cc6080830185615785565b8260a0830152979650505050505050565b600061014082840312156157f057600080fd5b6157f861538e565b9050615803826155f4565b81526020820151602082015260408201516040820152606082015160608201526080820151608082015260a082015160a082015261584360c083016155cc565b60c082015260e082015160e082015261010080830151818301525061012080830151818301525092915050565b60006101e0828403121561588357600080fd5b60405160c0810181811067ffffffffffffffff821117156158a6576158a6615378565b6040526158b384846157dd565b81526101408301516020820152610160830151604082015261018083015160608201526101a083015160808201526101c09092015160a083015250919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115615207576152076158f3565b805180516001600160a01b031683526020810151602084015260408101516040840152606081015160608401526080810151608084015260a081015160a084015260c081015161597060c085018215159052565b5060e081810151908401526101008082015190840152610120908101519083015260208101516101408301526040810151610160830152606081015161018083015260808101516101a083015260a001516101c090910152565b6101e08101615207828461591c565b600082516159eb81846020870161530e565b9190910192915050565b8183823760009101908152919050565b600060208284031215615a1757600080fd5b815167ffffffffffffffff80821115615a2f57600080fd5b818401915084601f830112615a4357600080fd5b815181811115615a5557615a55615378565b604051601f8201601f19908116603f01168101908382118183101715615a7d57615a7d615378565b81604052828152876020848701011115615a9657600080fd5b615aa783602083016020880161530e565b979650505050505050565b8082028115828204841417615207576152076158f3565b600060208284031215615adb57600080fd5b5051919050565b81810381811115615207576152076158f3565b60008060408385031215615b0857600080fd5b505080516020909101519092909150565b6001600160a01b038516815260208101849052604081018390526080810160038310615b4757615b4761576f565b82606083015295945050505050565b8381526060810160058410615b6d57615b6d61576f565b602082019390935260400152919050565b6102208101615b8d828661591c565b836101e0830152821515610200830152949350505050565b60006101408284031215615bb857600080fd5b61537183836157dd565b600060c08284031215615bd457600080fd5b60405160c0810181811067ffffffffffffffff82111715615bf757615bf7615378565b8060405250825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a0830151615c36816153dc565b60a08201529392505050565b600082615c5f57634e487b7160e01b600052601260045260246000fd5b500490565b600481106157955761579561576f565b6001600160a01b03815116825260208101516020830152604081015160408301526060810151615ca76060840182615c64565b505050565b608081016152078284615c74565b600060e0820190506001600160a01b038085511683526020850151602084015280604086015116604084015250606084015160608301526080840151608083015260a0840151615d0d60a0840182615c64565b508260c08301529392505050565b60c08101615d298286615c74565b6001600160a01b0393909316608082015260a00152919050565b60a08101615d518285615c74565b6001600160a01b03831660808301529392505050565b600060c0820190506001600160a01b0380861683528085511660208401525060208401516040830152604084015160608301526060840151615dac6080840182615785565b508260a083015294935050505056fea2646970667358221220facbb2ac7710251165f9e6c004977cba5593ba7a4a952e0f526731d8b665c7f064736f6c63430008110033

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

000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c000000000000000000000000de5750071caca8db173fc6543d23d0bcacacfec300000000000000000000000004a5e3cf21b0080b72facdca634349a56982d497000000000000000000000000aa379dd7ec0bae467490e89bb2055a7e01231b8f000000000000000000000000000000000000000000001a784379d99db42000000000000000000000000000000000000000000000000000000000000000000005

-----Decoded View---------------
Arg [0] : _storageT (address): 0xcFa6ebD475d89dB04cAd5A756fff1cb2BC5bE33c
Arg [1] : _nftRewards (address): 0xde5750071CacA8db173FC6543D23d0BCACACFEC3
Arg [2] : _pairInfos (address): 0x04a5e3cf21B0080B72fAcDca634349A56982D497
Arg [3] : _referrals (address): 0xAA379DD7Ec0bae467490e89bB2055A7e01231b8f
Arg [4] : _maxPosDai (uint256): 125000000000000000000000
Arg [5] : _marketOrdersTimeout (uint256): 5

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000cfa6ebd475d89db04cad5a756fff1cb2bc5be33c
Arg [1] : 000000000000000000000000de5750071caca8db173fc6543d23d0bcacacfec3
Arg [2] : 00000000000000000000000004a5e3cf21b0080b72facdca634349a56982d497
Arg [3] : 000000000000000000000000aa379dd7ec0bae467490e89bb2055a7e01231b8f
Arg [4] : 000000000000000000000000000000000000000000001a784379d99db4200000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000005


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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