GLMR Price: $0.51 (-1.39%)
Gas: 163 GWei

Contract

0xE4Dfb933b03287Ef508c7517c231443D68Cc1F37

Overview

GLMR Balance

Moonbeam Chain LogoMoonbeam Chain LogoMoonbeam Chain Logo0 GLMR

GLMR Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
Post Prices45304482023-09-28 6:04:12182 days ago1695881052IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.0204515125
Post Prices45301702023-09-28 5:08:18182 days ago1695877698IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.02078066127.01187778
Post Prices45297552023-09-28 3:44:06182 days ago1695872646IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.0204515125
Post Prices45296172023-09-28 3:16:12182 days ago1695870972IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.0203875125
Post Prices45294792023-09-28 2:48:18182 days ago1695869298IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.0204515125
Post Prices45290602023-09-28 1:24:12182 days ago1695864252IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.0203875125
Post Prices45289212023-09-28 0:56:06182 days ago1695862566IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.0204515125
Post Prices45287822023-09-28 0:28:12182 days ago1695860892IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.0203875125
Post Prices45286422023-09-28 0:00:12182 days ago1695859212IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.0204515125
Post Prices45276802023-09-27 20:44:19182 days ago1695847459IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.0204515125
Post Prices45275412023-09-27 20:16:11182 days ago1695845771IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.02041777125.18561617
Post Prices45274022023-09-27 19:48:12182 days ago1695844092IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.02120464129.60323054
Post Prices45271242023-09-27 18:52:06182 days ago1695840726IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.02293985140.20886227
Post Prices45268492023-09-27 17:56:24182 days ago1695837384IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.02435356149.31675813
Post Prices45267122023-09-27 17:28:12182 days ago1695835692IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.0252102154.08532938
Post Prices45265742023-09-27 17:00:12182 days ago1695834012IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.02676608164.10842802
Post Prices45264492023-09-27 16:34:36182 days ago1695832476IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.02804713171.42470194
Post Prices45261632023-09-27 15:36:22182 days ago1695828982IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.031029190.24528422
Post Prices45260272023-09-27 15:08:18183 days ago1695827298IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.03194575195.25313918
Post Prices45257502023-09-27 14:12:18183 days ago1695823938IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.02932241179.2192423
Post Prices45256102023-09-27 13:44:12183 days ago1695822252IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.02829787173.50016803
Post Prices45254712023-09-27 13:16:12183 days ago1695820572IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.03022181184.71638483
Post Prices45253312023-09-27 12:48:06183 days ago1695818886IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.03171567194.45540463
Post Prices45251932023-09-27 12:20:12183 days ago1695817212IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.03222712196.97287797
Post Prices45249162023-09-27 11:24:24183 days ago1695813864IN
0xE4Dfb933...D68Cc1F37
0 GLMR0.03331315203.61068892
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
UniswapAnchoredView

Compiler Version
v0.7.6+commit.7338295f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 5 : UniswapAnchoredView.sol
// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.7.6;
pragma experimental ABIEncoderV2;

import "../OpenOraclePriceData.sol";
import "./UniswapConfig.sol";
import "./UniswapLib.sol";

interface RegistryForUAV {
    function getPriceForAsset(address cToken) external view returns (uint256);
}

struct Observation {
    uint timestamp;
    uint acc;
}

contract UniswapAnchoredView is UniswapConfig {
    using FixedPoint for *;

    string[] public autoPokingSymbols;

    /// @notice The Open Oracle Price Data contract
    OpenOraclePriceData public immutable priceData;

    /// @notice The number of wei in 1 ETH
    uint public constant ethBaseUnit = 1e18;

    /// @notice A common scaling factor to maintain precision
    uint public constant expScale = 1e18;

    /// @notice The Open Oracle Reporter
    address public immutable reporter;

    /// @notice The highest ratio of the new price to the anchor price that will still trigger the price to be updated
    uint public immutable upperBoundAnchorRatio;

    /// @notice The lowest ratio of the new price to the anchor price that will still trigger the price to be updated
    uint public immutable lowerBoundAnchorRatio;

    /// @notice The minimum amount of time in seconds required for the old uniswap price accumulator to be replaced
    uint public immutable anchorPeriod;

    /// @notice Official prices by symbol hash
    mapping(bytes32 => uint) public prices;

    /// @notice Last 'Official price' update timestamp
    /// OLA_ADDITIONS : This field
    mapping(bytes32 => uint) public pricesLastUpdate;

    /// @notice Circuit breaker for using anchor price oracle directly, ignoring reporter
    bool public reporterInvalidated;

    /// @notice The old observation for each symbolHash
    mapping(bytes32 => Observation) public oldObservations;

    /// @notice The new observation for each symbolHash
    mapping(bytes32 => Observation) public newObservations;

    /// @notice The event emitted when new prices are posted but the stored price is not updated due to the anchor
    event PriceGuarded(string symbol, uint reporter, uint anchor);

    /// @notice The event emitted when the stored price is updated
    event PriceUpdated(string symbol, uint price);

    /// @notice The event emitted when anchor price is updated
    event AnchorPriceUpdated(string symbol, uint anchorPrice, uint oldTimestamp, uint newTimestamp);

    /// @notice The event emitted when the uniswap window changes
    event UniswapWindowUpdated(bytes32 indexed symbolHash, uint oldTimestamp, uint newTimestamp, uint oldPrice, uint newPrice);

    /// @notice The event emitted when reporter invalidates itself
    event ReporterInvalidated(address reporter);

    bytes32 constant ethHash = keccak256(abi.encodePacked("ETH"));
    bytes32 constant rotateHash = keccak256(abi.encodePacked("rotate"));
    string public referenceAssetSymbol;
    bytes32 public referenceAssetHash;
    uint public usdBaseUnit;
    address public registry;

    /**
     * @notice Construct a uniswap anchored view for a set of token configurations
     * @dev Note that to avoid immature TWAPs, the system must run for at least a single anchorPeriod before using.
     * @param reporter_ The reporter whose prices are to be used
     * @param referenceAssetSymbol_ The asset('s symbol) to measure the prices of all other (non fixed) assets against.
     * @param usdBaseUnit_ Amount that equal to 1 scaled by the base USD token decimals.
     * @param anchorToleranceMantissa_ The percentage tolerance that the reporter may deviate from the uniswap anchor
     * @param anchorPeriod_ The minimum amount of time required for the old uniswap price accumulator to be replaced
     * @param configs The static token configurations which define what prices are supported and how
     */
    constructor(OpenOraclePriceData priceData_,
                address reporter_,
                string memory referenceAssetSymbol_,
                uint usdBaseUnit_,
                uint anchorToleranceMantissa_,
                uint anchorPeriod_,
                address registry_,
                TokenConfig[] memory configs,
                string[] memory _autoPokingSymbols) UniswapConfig(configs) public {
        priceData = priceData_;
        reporter = reporter_;
        anchorPeriod = anchorPeriod_;
        registry = registry_;
        autoPokingSymbols = _autoPokingSymbols;

        referenceAssetSymbol = referenceAssetSymbol_;
        referenceAssetHash = keccak256(abi.encodePacked(referenceAssetSymbol));
        usdBaseUnit = usdBaseUnit_;

        // Allow the tolerance to be whatever the deployer chooses, but prevent under/overflow (and prices from being 0)
        upperBoundAnchorRatio = anchorToleranceMantissa_ > uint(-1) - 100e16 ? uint(-1) : 100e16 + anchorToleranceMantissa_;
        lowerBoundAnchorRatio = anchorToleranceMantissa_ < 100e16 ? 100e16 - anchorToleranceMantissa_ : 1;

        for (uint i = 0; i < configs.length; i++) {
            TokenConfig memory config = configs[i];
            require(config.baseUnit > 0, "baseUnit must be greater than zero");
            address uniswapMarket = config.uniswapMarket;
            if (config.priceSource == PriceSource.REPORTER || config.priceSource == PriceSource.UNISWAP) {
                require(uniswapMarket != address(0), "reported prices must have an anchor");
                bytes32 symbolHash = config.symbolHash;
                uint cumulativePrice = currentCumulativePrice(config);
                oldObservations[symbolHash].timestamp = block.timestamp;
                newObservations[symbolHash].timestamp = block.timestamp;
                oldObservations[symbolHash].acc = cumulativePrice;
                newObservations[symbolHash].acc = cumulativePrice;
                emit UniswapWindowUpdated(symbolHash, block.timestamp, block.timestamp, cumulativePrice, cumulativePrice);
            } else {
                require(uniswapMarket == address(0), "only reported prices utilize an anchor");
            }

            require(PriceSource.ORACLE != config.priceSource || address(0) != registry_, "Registry address required for using oracle asset");
        }
    }

    /**
     * @notice Get the array of symbols that can be auto poked.
     */
    function getAllAutoPokingSymbols() external view returns (string[] memory) {
        return autoPokingSymbols;
    }

    /**
     * @notice Get the official price for a symbol
     * @param symbol The symbol to fetch the price of
     * @return Price denominated in USD, with 6 decimals
     */
    function price(string memory symbol) external view returns (uint) {
        TokenConfig memory config = getTokenConfigBySymbol(symbol);
        return priceInternal(config);
    }

    function priceInternal(TokenConfig memory config) internal view returns (uint) {
        if (config.priceSource == PriceSource.REPORTER || config.priceSource == PriceSource.UNISWAP || config.priceSource == PriceSource.SIGNED_ONLY || config.priceSource == PriceSource.ORACLE) return prices[config.symbolHash];
        if (config.priceSource == PriceSource.FIXED_USD) return config.fixedPrice;
        if (config.priceSource == PriceSource.FIXED_ETH) {
            uint usdPerEth = prices[ethHash];
            require(usdPerEth > 0, "ETH price not set, cannot convert to dollars");
            return mul(usdPerEth, config.fixedPrice) / ethBaseUnit;
        }
    }

    /**
     * @notice Get the price an asset
     * @param asset The asset to get the price of
     * @return The asset price mantissa (scaled by 1e18).
     *  Zero means the price is unavailable.
     */
    function getAssetPrice(address asset) external view returns (uint) {
        return getAssetPriceInternal(asset);
    }

    /**
     * @notice Get the price update timestamp for the asset
     * @param asset The asset address for price update timestamp retrieval.
     * @return Last price update timestamp for the asset
     */
    function getAssetPriceUpdateTimestamp(address asset) external view returns (uint) {
        return getAssetPriceUpdateTimestampInternal(asset);
    }

    /**
     * @notice Get the underlying price of a cToken
     * @dev Implements the PriceOracle interface for Compound v2.
     * @param cToken The cToken address for price retrieval
     * @return Price denominated in USD, with 18 decimals, for the given cToken address
     */
    function getUnderlyingPrice(address cToken) external view returns (uint) {
        return getAssetPriceInternal(CErc20ForUniswapConfig(cToken).underlying());
    }

    /**
     * OLA_ADDITIONS : This function
     * @notice Get the price update timestamp for the cToken underlying
     * @dev Implements the PriceOracle interface for Compound v2.
     * @param cToken The cToken address for price update timestamp retrieval.
     * @return Last price update timestamp for the cToken underlying asset
     */
    function getUnderlyingPriceUpdateTimestamp(address cToken) external view returns (uint) {
        return getAssetPriceUpdateTimestampInternal(CErc20ForUniswapConfig(cToken).underlying());
    }

    /**
     * @notice Post open oracle reporter prices, and recalculate stored price by comparing to anchor
     * @dev We let anyone pay to post anything, but only prices from configured reporter will be stored in the view.
     * @param messages The messages to post to the oracle
     * @param signatures The signatures for the corresponding messages
     * @param symbols The symbols to compare to anchor for authoritative reading
     */
    function postPrices(bytes[] calldata messages, bytes[] calldata signatures, string[] calldata symbols) external {
        require(messages.length == signatures.length, "messages and signatures must be 1:1");

        // Save the prices
        for (uint i = 0; i < messages.length; i++) {
            TokenConfig memory config = getTokenConfigBySymbol(symbols[i]);
            if (config.priceSource == PriceSource.REPORTER || config.priceSource == PriceSource.SIGNED_ONLY) {
                priceData.put(messages[i], signatures[i]);
            }
        }

        // OLA_ADDITIONS : Using 'core asset price' instead of 'ethPrice
        uint referenceAssetPrice = fetchReferenceAssetPrice();

        // Try to update the view storage
        for (uint i = 0; i < symbols.length; i++) {
            postPriceInternal(symbols[i], referenceAssetPrice);
        }
    }

    /**
     * @notice Post open oracle reporter prices, and recalculate stored price by comparing to anchor
     * @dev We let anyone pay to post anything, but only prices from configured reporter will be stored in the view.
     * @param symbols The symbols to compare to anchor for authoritative reading
     */
    function freshenPrices(string[] calldata symbols) external {
        // OLA_ADDITIONS : Using 'core asset price' instead of 'ethPrice
        uint referenceAssetPrice = fetchReferenceAssetPrice();

        // Try to update the view storage
        for (uint i = 0; i < symbols.length; i++) {
            postPriceInternal(symbols[i], referenceAssetPrice);
        }
    }

    /**
     * @notice Recalculates stored prices for all by comparing to anchor
     * @dev Only prices from configured UNISWAP will be recalculated in the view.
     */
    function freshensAllPrices() external {
        string[] memory symbols = autoPokingSymbols;
        // OLA_ADDITIONS : Using 'core asset price' instead of 'ethPrice
        uint referenceAssetPrice = fetchReferenceAssetPrice();

        // Try to update the view storage
        for (uint i = 0; i < symbols.length; i++) {
            postPriceInternal(symbols[i], referenceAssetPrice);
        }
    }

    function getAssetPriceInternal(address asset) internal view returns (uint) {
        TokenConfig memory config;

        config = getTokenConfigByUnderlying(asset);

        // Comptroller needs prices in the format: ${raw price} * 1e(36 - baseUnit)
        // Since the prices in this view have 6 decimals, we must scale them by 1e(36 - 6 - baseUnit)
        return mul(1e30, priceInternal(config)) / config.baseUnit;
    }

    function getAssetPriceUpdateTimestampInternal(address asset) internal view returns (uint) {
        TokenConfig memory config;

        config = getTokenConfigByUnderlying(asset);

        return pricesLastUpdate[config.symbolHash];
    }

    // OLA_ADDITIONS : Using 'referenceAssetPrice' instead of 'ethPrice'
    function postPriceInternal(string memory symbol, uint referenceAssetPrice) internal {
        TokenConfig memory config = getTokenConfigBySymbol(symbol);
        require(config.priceSource == PriceSource.REPORTER ||
                config.priceSource == PriceSource.UNISWAP ||
                config.priceSource == PriceSource.SIGNED_ONLY ||
                config.priceSource == PriceSource.ORACLE, "only reporter, uniswap, oracle or signed-only prices get posted");

        // OLA_ADDITIONS : Updating 'last price update timestamp' together with the prices
        uint lastUpdateTimestamp = block.timestamp;
        bytes32 symbolHash = keccak256(abi.encodePacked(symbol));

        if (referenceAssetHash == symbolHash) {
            prices[referenceAssetHash] = referenceAssetPrice;
            pricesLastUpdate[referenceAssetHash] = lastUpdateTimestamp;
        }

        // OLA_ADDITIONS : Support of 'signed-only' price posting
        // Signed-Only prices do not require 'anchorPrice' (which is taken from a pair)
        if (config.priceSource == PriceSource.SIGNED_ONLY) {
            uint reporterPrice = priceData.getPrice(reporter, symbol);

            prices[symbolHash] = reporterPrice;
            // OLA_ADDITIONS : Updating price timestamp
            pricesLastUpdate[symbolHash] = lastUpdateTimestamp;

            emit PriceUpdated(symbol, reporterPrice);

            return;
        }

        if (config.priceSource == PriceSource.ORACLE) {
            uint oraclePrice = getPriceFromOracle(config);
            prices[symbolHash] = oraclePrice;
            pricesLastUpdate[symbolHash] = lastUpdateTimestamp;
            emit PriceUpdated(symbol, oraclePrice);
        }


        uint anchorPrice;
        if (symbolHash == referenceAssetHash) {
            anchorPrice = referenceAssetPrice;
        } else {
            uint256 conversionFactor = config.isDirectMarket? config.priceScale: referenceAssetPrice;
            anchorPrice = fetchAnchorPrice(symbol, config, conversionFactor);
        }


        if (config.priceSource == PriceSource.UNISWAP || reporterInvalidated) {
            prices[symbolHash] = anchorPrice;
            // OLA_ADDITIONS : Updating price timestamp
            pricesLastUpdate[symbolHash] = lastUpdateTimestamp;
            emit PriceUpdated(symbol, anchorPrice);
        } else {
            // OLA_ADDITIONS : Moves 'priceData.getPrice' inside to save gas on swap based asses
            uint reporterPrice = priceData.getPrice(reporter, symbol);
            if (isWithinAnchor(reporterPrice, anchorPrice)) {
                prices[symbolHash] = reporterPrice;
                // OLA_ADDITIONS : Updating price timestamp
                pricesLastUpdate[symbolHash] = lastUpdateTimestamp;
                emit PriceUpdated(symbol, reporterPrice);
            } else {
                emit PriceGuarded(symbol, reporterPrice, anchorPrice);
            }
        }
    }

    function isWithinAnchor(uint reporterPrice, uint anchorPrice) internal view returns (bool) {
        if (reporterPrice > 0) {
            uint anchorRatio = mul(anchorPrice, 100e16) / reporterPrice;
            return anchorRatio <= upperBoundAnchorRatio && anchorRatio >= lowerBoundAnchorRatio;
        }
        return false;
    }

    /**
     * @dev Fetches the current token/eth price accumulator from uniswap.
     */
    function currentCumulativePrice(TokenConfig memory config) internal view returns (uint) {
        (uint cumulativePrice0, uint cumulativePrice1,) = UniswapV2OracleLibrary.currentCumulativePrices(config.uniswapMarket);
        if (config.isUniswapReversed) {
            return cumulativePrice1;
        } else {
            return cumulativePrice0;
        }
    }

    /**
     * @dev Fetches the current eth/usd price from uniswap, with 6 decimals of precision.
     *  Conversion factor is 1e18 for eth/usdc market, since we decode uniswap price statically with 18 decimals.
     */
//    function fetchEthPrice() internal returns (uint) {
//        return fetchAnchorPrice("ETH", getTokenConfigBySymbolHash(ethHash), ethBaseUnit);
//    }

    function getPriceFromOracle(TokenConfig memory config) internal view returns (uint256 price) {
        price = RegistryForUAV(registry).getPriceForAsset(config.underlying);
        price = mul(price, 1e6);
        price = mul(price, config.baseUnit);
        price = price / 1e36;
    }

    /**
     * @dev Fetches the current core/usd price from uniswap, with 6 decimals of precision.
     *  Conversion factor is 1e18 for core/usdc market, since we decode uniswap price statically with 18 decimals.
     */
    function fetchReferenceAssetPrice() internal returns (uint) {
        uint256 price;
        TokenConfig memory config = getTokenConfigBySymbolHash(referenceAssetHash);

        if (PriceSource.REPORTER == config.priceSource || PriceSource.UNISWAP == config.priceSource) {
            price = fetchAnchorPrice(referenceAssetSymbol, config, ethBaseUnit);
        } else if (PriceSource.ORACLE == config.priceSource) {
            price = getPriceFromOracle(config);
        } else {
            price = priceData.getPrice(reporter, referenceAssetSymbol);
        }
        require(price != 0, "Reference asset price unavailable");
        
        return price;
    }

    /**
     * @dev Fetches the current token/usd price from uniswap, with 6 decimals of precision.
     * @param conversionFactor 1e18 if seeking the ETH price, and a 6 decimal ETH-USDC price in the case of other assets
     */
    function fetchAnchorPrice(string memory symbol, TokenConfig memory config, uint conversionFactor) internal virtual returns (uint) {
        (uint nowCumulativePrice, uint oldCumulativePrice, uint oldTimestamp) = pokeWindowValues(config);

        // This should be impossible, but better safe than sorry
        require(block.timestamp > oldTimestamp, "now must come after before");
        uint timeElapsed = block.timestamp - oldTimestamp;

        // Calculate uniswap time-weighted average price
        // Underflow is a property of the accumulators: https://uniswap.org/audit.html#orgc9b3190
        FixedPoint.uq112x112 memory priceAverage = FixedPoint.uq112x112(uint224((nowCumulativePrice - oldCumulativePrice) / timeElapsed));
        uint rawUniswapPriceMantissa = priceAverage.decode112with18();
        uint unscaledPriceMantissa = mul(rawUniswapPriceMantissa, conversionFactor);
        uint anchorPrice;

        // Adjust rawUniswapPrice according to the units of the non-ETH asset
        // In the case of ETH, we would have to scale by 1e6 / USDC_UNITS, but since baseUnit2 is 1e6 (USDC), it cancels

        // In the case of non-ETH tokens
        // a. pokeWindowValues already handled uniswap reversed cases, so priceAverage will always be Token/ETH TWAP price.
        // b. conversionFactor Scale = 1e(18 + 6 - tokenDecimals)). We assume that tokenDecimals is 18. If not, than probably there is a mistake here.
        // unscaledPriceMantissa = priceAverage(token/ETH TWAP price) * expScale * conversionFactor
        // so ->
        // anchorPrice = priceAverage * tokenBaseUnit / ethBaseUnit * ETH_price * 1e6
        //             = priceAverage * conversionFactor * tokenBaseUnit / ethBaseUnit
        //             = unscaledPriceMantissa / expScale * tokenBaseUnit / ethBaseUnit
        anchorPrice = mul(unscaledPriceMantissa, config.baseUnit) / ethBaseUnit / expScale;

        if (keccak256(abi.encodePacked(symbol)) == referenceAssetHash) {
            anchorPrice = mul(anchorPrice, 1e6) / usdBaseUnit;
        }

        emit AnchorPriceUpdated(symbol, anchorPrice, oldTimestamp, block.timestamp);

        return anchorPrice;
    }

    /**
     * @dev Get time-weighted average prices for a token at the current timestamp.
     *  Update new and old observations of lagging window if period elapsed.
     */
    function pokeWindowValues(TokenConfig memory config) internal returns (uint, uint, uint) {
        bytes32 symbolHash = config.symbolHash;
        uint cumulativePrice = currentCumulativePrice(config);

        Observation memory newObservation = newObservations[symbolHash];

        // Update new and old observations if elapsed time is greater than or equal to anchor period
        uint timeElapsed = block.timestamp - newObservation.timestamp;
        if (timeElapsed >= anchorPeriod) {
            oldObservations[symbolHash].timestamp = newObservation.timestamp;
            oldObservations[symbolHash].acc = newObservation.acc;

            newObservations[symbolHash].timestamp = block.timestamp;
            newObservations[symbolHash].acc = cumulativePrice;
            emit UniswapWindowUpdated(config.symbolHash, newObservation.timestamp, block.timestamp, newObservation.acc, cumulativePrice);
        }
        return (cumulativePrice, oldObservations[symbolHash].acc, oldObservations[symbolHash].timestamp);
    }

    /**
     * @notice Invalidate the reporter, and fall back to using anchor directly in all cases
     * @dev Only the reporter may sign a message which allows it to invalidate itself.
     *  To be used in cases of emergency, if the reporter thinks their key may be compromised.
     * @param message The data that was presumably signed
     * @param signature The fingerprint of the data + private key
     */
    function invalidateReporter(bytes memory message, bytes memory signature) external {
        (string memory decodedMessage, ) = abi.decode(message, (string, address));
        require(keccak256(abi.encodePacked(decodedMessage)) == rotateHash, "invalid message must be 'rotate'");
        require(source(message, signature) == reporter, "invalidation message must come from the reporter");
        reporterInvalidated = true;
        emit ReporterInvalidated(reporter);
    }

    /**
     * @notice Recovers the source address which signed a message
     * @dev Comparing to a claimed address would add nothing,
     *  as the caller could simply perform the recover and claim that address.
     * @param message The data that was presumably signed
     * @param signature The fingerprint of the data + private key
     * @return The source address which signed the message, presumably
     */
    function source(bytes memory message, bytes memory signature) public pure returns (address) {
        (bytes32 r, bytes32 s, uint8 v) = abi.decode(signature, (bytes32, bytes32, uint8));
        bytes32 hash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(message)));
        return ecrecover(hash, v, r, s);
    }

    /// @dev Overflow proof multiplication
    function mul(uint a, uint b) internal pure returns (uint) {
        if (a == 0) return 0;
        uint c = a * b;
        require(c / a == b, "multiplication overflow");
        return c;
    }
}

File 2 of 5 : OpenOraclePriceData.sol
// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.7.6;

import "./OpenOracleData.sol";

/**
 * @title The Open Oracle Price Data Contract
 * @notice Values stored in this contract should represent a USD price with 6 decimals precision
 * @author Compound Labs, Inc.
 */
contract OpenOraclePriceData is OpenOracleData {
    ///@notice The event emitted when a source writes to its storage
    event Write(address indexed source, string key, uint64 timestamp, uint64 value);
    ///@notice The event emitted when the timestamp on a price is invalid and it is not written to storage
    event NotWritten(uint64 priorTimestamp, uint256 messageTimestamp, uint256 blockTimestamp);

    ///@notice The fundamental unit of storage for a reporter source
    struct Datum {
        uint64 timestamp;
        uint64 value;
    }

    /**
     * @dev The most recent authenticated data from all sources.
     *  This is private because dynamic mapping keys preclude auto-generated getters.
     */
    mapping(address => mapping(string => Datum)) private data;

    /**
     * @notice Write a bunch of signed datum to the authenticated storage mapping
     * @param message The payload containing the timestamp, and (key, value) pairs
     * @param signature The cryptographic signature of the message payload, authorizing the source to write
     * @return The keys that were written
     */
    function put(bytes calldata message, bytes calldata signature) external returns (string memory) {
        (address source, uint64 timestamp, string memory key, uint64 value) = decodeMessage(message, signature);
        return putInternal(source, timestamp, key, value);
    }

    function putInternal(address source, uint64 timestamp, string memory key, uint64 value) internal returns (string memory) {
        // Only update if newer than stored, according to source
        Datum storage prior = data[source][key];
        if (timestamp > prior.timestamp && timestamp < block.timestamp + 60 minutes && source != address(0)) {
            data[source][key] = Datum(timestamp, value);
            emit Write(source, key, timestamp, value);
        } else {
            emit NotWritten(prior.timestamp, timestamp, block.timestamp);
        }
        return key;
    }

    function decodeMessage(bytes calldata message, bytes calldata signature) internal returns (address, uint64, string memory, uint64) {
        // Recover the source address
        address source = source(message, signature);

        // Decode the message and check the kind
        (string memory kind, uint64 timestamp, string memory key, uint64 value) = abi.decode(message, (string, uint64, string, uint64));
        require(keccak256(abi.encodePacked(kind)) == keccak256(abi.encodePacked("prices")), "Kind of data must be 'prices'");
        return (source, timestamp, key, value);
    }

    /**
     * @notice Read a single key from an authenticated source
     * @param source The verifiable author of the data
     * @param key The selector for the value to return
     * @return The claimed Unix timestamp for the data and the price value (defaults to (0, 0))
     */
    function get(address source, string calldata key) external view returns (uint64, uint64) {
        Datum storage datum = data[source][key];
        return (datum.timestamp, datum.value);
    }

    /**
     * @notice Read only the value for a single key from an authenticated source
     * @param source The verifiable author of the data
     * @param key The selector for the value to return
     * @return The price value (defaults to 0)
     */
    function getPrice(address source, string calldata key) external view returns (uint64) {
        return data[source][key].value;
    }
}

File 3 of 5 : UniswapConfig.sol
// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.7.6;
pragma experimental ABIEncoderV2;

interface CErc20ForUniswapConfig {
    function underlying() external view returns (address);
}

contract UniswapConfig {
    /// @dev Describe how to interpret the fixedPrice in the TokenConfig.
    enum PriceSource {
        FIXED_ETH, /// implies the fixedPrice is a constant multiple of the ETH price (which varies)
        FIXED_USD, /// implies the fixedPrice is a constant multiple of the USD price (which is 1)
        REPORTER,   /// implies the price is set by the reporter
        UNISWAP,     /// implies the price is set by uniswap
        SIGNED_ONLY, /// implies the price is set by a reporter without a matching pair
        ORACLE       /// implies the price is being fetched from an oracle
    }
    
    /// @dev Describe how the USD price should be determined for an asset.
    ///  There should be 1 TokenConfig object for each supported asset, passed in the constructor.
    struct TokenConfig {
        address underlying;
        bytes32 symbolHash;
        uint256 baseUnit;
        PriceSource priceSource;
        uint256 fixedPrice;
        address uniswapMarket;
        bool isUniswapReversed;
        bool isDirectMarket; // Indicated that the market is to a stable coin, no need to use a reference asset
        uint256 priceScale; // Should be (18 + 6 - ScaleTokenDecimals) - ScaleTokenDecimals is the decimals of the token we want the price in. (Ex. BNB in USDC, this value will be (18 + 6 - [USDC's decimals]))
    }

    /// @notice The max number of tokens this contract is hardcoded to support
    /// @dev Do not change this variable without updating all the fields throughout the contract.
    uint public constant maxTokens = 15;

    /// @notice The number of tokens this contract actually supports
    uint public immutable numTokens;

    address internal immutable underlying00;
    address internal immutable underlying01;
    address internal immutable underlying02;
    address internal immutable underlying03;
    address internal immutable underlying04;
    address internal immutable underlying05;
    address internal immutable underlying06;
    address internal immutable underlying07;
    address internal immutable underlying08;
    address internal immutable underlying09;
    address internal immutable underlying10;
    address internal immutable underlying11;
    address internal immutable underlying12;
    address internal immutable underlying13;
    address internal immutable underlying14;
    // address internal immutable underlying15;
    // address internal immutable underlying16;
    // address internal immutable underlying17;
    // address internal immutable underlying18;
    // address internal immutable underlying19;
    // address internal immutable underlying20;
    // address internal immutable underlying21;
    // address internal immutable underlying22;
    // address internal immutable underlying23;
    // address internal immutable underlying24;
    // address internal immutable underlying25;
    // address internal immutable underlying26;
    // address internal immutable underlying27;
    // address internal immutable underlying28;
    // address internal immutable underlying29;

    bytes32 internal immutable symbolHash00;
    bytes32 internal immutable symbolHash01;
    bytes32 internal immutable symbolHash02;
    bytes32 internal immutable symbolHash03;
    bytes32 internal immutable symbolHash04;
    bytes32 internal immutable symbolHash05;
    bytes32 internal immutable symbolHash06;
    bytes32 internal immutable symbolHash07;
    bytes32 internal immutable symbolHash08;
    bytes32 internal immutable symbolHash09;
    bytes32 internal immutable symbolHash10;
    bytes32 internal immutable symbolHash11;
    bytes32 internal immutable symbolHash12;
    bytes32 internal immutable symbolHash13;
    bytes32 internal immutable symbolHash14;
    // bytes32 internal immutable symbolHash15;
    // bytes32 internal immutable symbolHash16;
    // bytes32 internal immutable symbolHash17;
    // bytes32 internal immutable symbolHash18;
    // bytes32 internal immutable symbolHash19;
    // bytes32 internal immutable symbolHash20;
    // bytes32 internal immutable symbolHash21;
    // bytes32 internal immutable symbolHash22;
    // bytes32 internal immutable symbolHash23;
    // bytes32 internal immutable symbolHash24;
    // bytes32 internal immutable symbolHash25;
    // bytes32 internal immutable symbolHash26;
    // bytes32 internal immutable symbolHash27;
    // bytes32 internal immutable symbolHash28;
    // bytes32 internal immutable symbolHash29;

    uint256 internal immutable baseUnit00;
    uint256 internal immutable baseUnit01;
    uint256 internal immutable baseUnit02;
    uint256 internal immutable baseUnit03;
    uint256 internal immutable baseUnit04;
    uint256 internal immutable baseUnit05;
    uint256 internal immutable baseUnit06;
    uint256 internal immutable baseUnit07;
    uint256 internal immutable baseUnit08;
    uint256 internal immutable baseUnit09;
    uint256 internal immutable baseUnit10;
    uint256 internal immutable baseUnit11;
    uint256 internal immutable baseUnit12;
    uint256 internal immutable baseUnit13;
    uint256 internal immutable baseUnit14;
    // uint256 internal immutable baseUnit15;
    // uint256 internal immutable baseUnit16;
    // uint256 internal immutable baseUnit17;
    // uint256 internal immutable baseUnit18;
    // uint256 internal immutable baseUnit19;
    // uint256 internal immutable baseUnit20;
    // uint256 internal immutable baseUnit21;
    // uint256 internal immutable baseUnit22;
    // uint256 internal immutable baseUnit23;
    // uint256 internal immutable baseUnit24;
    // uint256 internal immutable baseUnit25;
    // uint256 internal immutable baseUnit26;
    // uint256 internal immutable baseUnit27;
    // uint256 internal immutable baseUnit28;
    // uint256 internal immutable baseUnit29;

    PriceSource internal immutable priceSource00;
    PriceSource internal immutable priceSource01;
    PriceSource internal immutable priceSource02;
    PriceSource internal immutable priceSource03;
    PriceSource internal immutable priceSource04;
    PriceSource internal immutable priceSource05;
    PriceSource internal immutable priceSource06;
    PriceSource internal immutable priceSource07;
    PriceSource internal immutable priceSource08;
    PriceSource internal immutable priceSource09;
    PriceSource internal immutable priceSource10;
    PriceSource internal immutable priceSource11;
    PriceSource internal immutable priceSource12;
    PriceSource internal immutable priceSource13;
    PriceSource internal immutable priceSource14;
    // PriceSource internal immutable priceSource15;
    // PriceSource internal immutable priceSource16;
    // PriceSource internal immutable priceSource17;
    // PriceSource internal immutable priceSource18;
    // PriceSource internal immutable priceSource19;
    // PriceSource internal immutable priceSource20;
    // PriceSource internal immutable priceSource21;
    // PriceSource internal immutable priceSource22;
    // PriceSource internal immutable priceSource23;
    // PriceSource internal immutable priceSource24;
    // PriceSource internal immutable priceSource25;
    // PriceSource internal immutable priceSource26;
    // PriceSource internal immutable priceSource27;
    // PriceSource internal immutable priceSource28;
    // PriceSource internal immutable priceSource29;

    uint256 internal immutable fixedPrice00;
    uint256 internal immutable fixedPrice01;
    uint256 internal immutable fixedPrice02;
    uint256 internal immutable fixedPrice03;
    uint256 internal immutable fixedPrice04;
    uint256 internal immutable fixedPrice05;
    uint256 internal immutable fixedPrice06;
    uint256 internal immutable fixedPrice07;
    uint256 internal immutable fixedPrice08;
    uint256 internal immutable fixedPrice09;
    uint256 internal immutable fixedPrice10;
    uint256 internal immutable fixedPrice11;
    uint256 internal immutable fixedPrice12;
    uint256 internal immutable fixedPrice13;
    uint256 internal immutable fixedPrice14;
    // uint256 internal immutable fixedPrice15;
    // uint256 internal immutable fixedPrice16;
    // uint256 internal immutable fixedPrice17;
    // uint256 internal immutable fixedPrice18;
    // uint256 internal immutable fixedPrice19;
    // uint256 internal immutable fixedPrice20;
    // uint256 internal immutable fixedPrice21;
    // uint256 internal immutable fixedPrice22;
    // uint256 internal immutable fixedPrice23;
    // uint256 internal immutable fixedPrice24;
    // uint256 internal immutable fixedPrice25;
    // uint256 internal immutable fixedPrice26;
    // uint256 internal immutable fixedPrice27;
    // uint256 internal immutable fixedPrice28;
    // uint256 internal immutable fixedPrice29;

    address internal immutable uniswapMarket00;
    address internal immutable uniswapMarket01;
    address internal immutable uniswapMarket02;
    address internal immutable uniswapMarket03;
    address internal immutable uniswapMarket04;
    address internal immutable uniswapMarket05;
    address internal immutable uniswapMarket06;
    address internal immutable uniswapMarket07;
    address internal immutable uniswapMarket08;
    address internal immutable uniswapMarket09;
    address internal immutable uniswapMarket10;
    address internal immutable uniswapMarket11;
    address internal immutable uniswapMarket12;
    address internal immutable uniswapMarket13;
    address internal immutable uniswapMarket14;
    // address internal immutable uniswapMarket15;
    // address internal immutable uniswapMarket16;
    // address internal immutable uniswapMarket17;
    // address internal immutable uniswapMarket18;
    // address internal immutable uniswapMarket19;
    // address internal immutable uniswapMarket20;
    // address internal immutable uniswapMarket21;
    // address internal immutable uniswapMarket22;
    // address internal immutable uniswapMarket23;
    // address internal immutable uniswapMarket24;
    // address internal immutable uniswapMarket25;
    // address internal immutable uniswapMarket26;
    // address internal immutable uniswapMarket27;
    // address internal immutable uniswapMarket28;
    // address internal immutable uniswapMarket29;

    bool internal immutable isUniswapReversed00;
    bool internal immutable isUniswapReversed01;
    bool internal immutable isUniswapReversed02;
    bool internal immutable isUniswapReversed03;
    bool internal immutable isUniswapReversed04;
    bool internal immutable isUniswapReversed05;
    bool internal immutable isUniswapReversed06;
    bool internal immutable isUniswapReversed07;
    bool internal immutable isUniswapReversed08;
    bool internal immutable isUniswapReversed09;
    bool internal immutable isUniswapReversed10;
    bool internal immutable isUniswapReversed11;
    bool internal immutable isUniswapReversed12;
    bool internal immutable isUniswapReversed13;
    bool internal immutable isUniswapReversed14;
    // bool internal immutable isUniswapReversed15;
    // bool internal immutable isUniswapReversed16;
    // bool internal immutable isUniswapReversed17;
    // bool internal immutable isUniswapReversed18;
    // bool internal immutable isUniswapReversed19;
    // bool internal immutable isUniswapReversed20;
    // bool internal immutable isUniswapReversed21;
    // bool internal immutable isUniswapReversed22;
    // bool internal immutable isUniswapReversed23;
    // bool internal immutable isUniswapReversed24;
    // bool internal immutable isUniswapReversed25;
    // bool internal immutable isUniswapReversed26;
    // bool internal immutable isUniswapReversed27;
    // bool internal immutable isUniswapReversed28;
    // bool internal immutable isUniswapReversed29;

    bool[30] internal isDirectMarkets;

    bool internal immutable isDirectMarket00;
    bool internal immutable isDirectMarket01;
    bool internal immutable isDirectMarket02;
    bool internal immutable isDirectMarket03;
    bool internal immutable isDirectMarket04;
    bool internal immutable isDirectMarket05;
    bool internal immutable isDirectMarket06;
    bool internal immutable isDirectMarket07;
    bool internal immutable isDirectMarket08;
    bool internal immutable isDirectMarket09;
    bool internal immutable isDirectMarket10;
    bool internal immutable isDirectMarket11;
    bool internal immutable isDirectMarket12;
    bool internal immutable isDirectMarket13;
    bool internal immutable isDirectMarket14;
    // bool internal immutable isDirectMarket15;
    // bool internal immutable isDirectMarket16;
    // bool internal immutable isDirectMarket17;
    // bool internal immutable isDirectMarket18;
    // bool internal immutable isDirectMarket19;
    // bool internal immutable isDirectMarket20;
    // bool internal immutable isDirectMarket21;
    // bool internal immutable isDirectMarket22;
    // bool internal immutable isDirectMarket23;
    // bool internal immutable isDirectMarket24;
    // bool internal immutable isDirectMarket25;
    // bool internal immutable isDirectMarket26;
    // bool internal immutable isDirectMarket27;
    // bool internal immutable isDirectMarket28;
    // bool internal immutable isDirectMarket29;

    uint256 internal immutable priceScale00;
    uint256 internal immutable priceScale01;
    uint256 internal immutable priceScale02;
    uint256 internal immutable priceScale03;
    uint256 internal immutable priceScale04;
    uint256 internal immutable priceScale05;
    uint256 internal immutable priceScale06;
    uint256 internal immutable priceScale07;
    uint256 internal immutable priceScale08;
    uint256 internal immutable priceScale09;
    uint256 internal immutable priceScale10;
    uint256 internal immutable priceScale11;
    uint256 internal immutable priceScale12;
    uint256 internal immutable priceScale13;
    uint256 internal immutable priceScale14;

    /**
     * @notice Construct an immutable store of configs into the contract data
     * @param configs The configs for the supported assets
     */
    constructor(TokenConfig[] memory configs) public {
        require(configs.length <= maxTokens, "too many configs");
        numTokens = configs.length;

        underlying00 = get(configs, 0).underlying;
        underlying01 = get(configs, 1).underlying;
        underlying02 = get(configs, 2).underlying;
        underlying03 = get(configs, 3).underlying;
        underlying04 = get(configs, 4).underlying;
        underlying05 = get(configs, 5).underlying;
        underlying06 = get(configs, 6).underlying;
        underlying07 = get(configs, 7).underlying;
        underlying08 = get(configs, 8).underlying;
        underlying09 = get(configs, 9).underlying;
        underlying10 = get(configs, 10).underlying;
        underlying11 = get(configs, 11).underlying;
        underlying12 = get(configs, 12).underlying;
        underlying13 = get(configs, 13).underlying;
        underlying14 = get(configs, 14).underlying;
        // underlying15 = get(configs, 15).underlying;
        // underlying16 = get(configs, 16).underlying;
        // underlying17 = get(configs, 17).underlying;
        // underlying18 = get(configs, 18).underlying;
        // underlying19 = get(configs, 19).underlying;
        // underlying20 = get(configs, 20).underlying;
        // underlying21 = get(configs, 21).underlying;
        // underlying22 = get(configs, 22).underlying;
        // underlying23 = get(configs, 23).underlying;
        // underlying24 = get(configs, 24).underlying;
        // underlying25 = get(configs, 25).underlying;
        // underlying26 = get(configs, 26).underlying;
        // underlying27 = get(configs, 27).underlying;
        // underlying28 = get(configs, 28).underlying;
        // underlying29 = get(configs, 29).underlying;

        symbolHash00 = get(configs, 0).symbolHash;
        symbolHash01 = get(configs, 1).symbolHash;
        symbolHash02 = get(configs, 2).symbolHash;
        symbolHash03 = get(configs, 3).symbolHash;
        symbolHash04 = get(configs, 4).symbolHash;
        symbolHash05 = get(configs, 5).symbolHash;
        symbolHash06 = get(configs, 6).symbolHash;
        symbolHash07 = get(configs, 7).symbolHash;
        symbolHash08 = get(configs, 8).symbolHash;
        symbolHash09 = get(configs, 9).symbolHash;
        symbolHash10 = get(configs, 10).symbolHash;
        symbolHash11 = get(configs, 11).symbolHash;
        symbolHash12 = get(configs, 12).symbolHash;
        symbolHash13 = get(configs, 13).symbolHash;
        symbolHash14 = get(configs, 14).symbolHash;
        // symbolHash15 = get(configs, 15).symbolHash;
        // symbolHash16 = get(configs, 16).symbolHash;
        // symbolHash17 = get(configs, 17).symbolHash;
        // symbolHash18 = get(configs, 18).symbolHash;
        // symbolHash19 = get(configs, 19).symbolHash;
        // symbolHash20 = get(configs, 20).symbolHash;
        // symbolHash21 = get(configs, 21).symbolHash;
        // symbolHash22 = get(configs, 22).symbolHash;
        // symbolHash23 = get(configs, 23).symbolHash;
        // symbolHash24 = get(configs, 24).symbolHash;
        // symbolHash25 = get(configs, 25).symbolHash;
        // symbolHash26 = get(configs, 26).symbolHash;
        // symbolHash27 = get(configs, 27).symbolHash;
        // symbolHash28 = get(configs, 28).symbolHash;
        // symbolHash29 = get(configs, 29).symbolHash;

        baseUnit00 = get(configs, 0).baseUnit;
        baseUnit01 = get(configs, 1).baseUnit;
        baseUnit02 = get(configs, 2).baseUnit;
        baseUnit03 = get(configs, 3).baseUnit;
        baseUnit04 = get(configs, 4).baseUnit;
        baseUnit05 = get(configs, 5).baseUnit;
        baseUnit06 = get(configs, 6).baseUnit;
        baseUnit07 = get(configs, 7).baseUnit;
        baseUnit08 = get(configs, 8).baseUnit;
        baseUnit09 = get(configs, 9).baseUnit;
        baseUnit10 = get(configs, 10).baseUnit;
        baseUnit11 = get(configs, 11).baseUnit;
        baseUnit12 = get(configs, 12).baseUnit;
        baseUnit13 = get(configs, 13).baseUnit;
        baseUnit14 = get(configs, 14).baseUnit;
        // baseUnit15 = get(configs, 15).baseUnit;
        // baseUnit16 = get(configs, 16).baseUnit;
        // baseUnit17 = get(configs, 17).baseUnit;
        // baseUnit18 = get(configs, 18).baseUnit;
        // baseUnit19 = get(configs, 19).baseUnit;
        // baseUnit20 = get(configs, 20).baseUnit;
        // baseUnit21 = get(configs, 21).baseUnit;
        // baseUnit22 = get(configs, 22).baseUnit;
        // baseUnit23 = get(configs, 23).baseUnit;
        // baseUnit24 = get(configs, 24).baseUnit;
        // baseUnit25 = get(configs, 25).baseUnit;
        // baseUnit26 = get(configs, 26).baseUnit;
        // baseUnit27 = get(configs, 27).baseUnit;
        // baseUnit28 = get(configs, 28).baseUnit;
        // baseUnit29 = get(configs, 29).baseUnit;

        priceSource00 = get(configs, 0).priceSource;
        priceSource01 = get(configs, 1).priceSource;
        priceSource02 = get(configs, 2).priceSource;
        priceSource03 = get(configs, 3).priceSource;
        priceSource04 = get(configs, 4).priceSource;
        priceSource05 = get(configs, 5).priceSource;
        priceSource06 = get(configs, 6).priceSource;
        priceSource07 = get(configs, 7).priceSource;
        priceSource08 = get(configs, 8).priceSource;
        priceSource09 = get(configs, 9).priceSource;
        priceSource10 = get(configs, 10).priceSource;
        priceSource11 = get(configs, 11).priceSource;
        priceSource12 = get(configs, 12).priceSource;
        priceSource13 = get(configs, 13).priceSource;
        priceSource14 = get(configs, 14).priceSource;
        // priceSource15 = get(configs, 15).priceSource;
        // priceSource16 = get(configs, 16).priceSource;
        // priceSource17 = get(configs, 17).priceSource;
        // priceSource18 = get(configs, 18).priceSource;
        // priceSource19 = get(configs, 19).priceSource;
        // priceSource20 = get(configs, 20).priceSource;
        // priceSource21 = get(configs, 21).priceSource;
        // priceSource22 = get(configs, 22).priceSource;
        // priceSource23 = get(configs, 23).priceSource;
        // priceSource24 = get(configs, 24).priceSource;
        // priceSource25 = get(configs, 25).priceSource;
        // priceSource26 = get(configs, 26).priceSource;
        // priceSource27 = get(configs, 27).priceSource;
        // priceSource28 = get(configs, 28).priceSource;
        // priceSource29 = get(configs, 29).priceSource;

        fixedPrice00 = get(configs, 0).fixedPrice;
        fixedPrice01 = get(configs, 1).fixedPrice;
        fixedPrice02 = get(configs, 2).fixedPrice;
        fixedPrice03 = get(configs, 3).fixedPrice;
        fixedPrice04 = get(configs, 4).fixedPrice;
        fixedPrice05 = get(configs, 5).fixedPrice;
        fixedPrice06 = get(configs, 6).fixedPrice;
        fixedPrice07 = get(configs, 7).fixedPrice;
        fixedPrice08 = get(configs, 8).fixedPrice;
        fixedPrice09 = get(configs, 9).fixedPrice;
        fixedPrice10 = get(configs, 10).fixedPrice;
        fixedPrice11 = get(configs, 11).fixedPrice;
        fixedPrice12 = get(configs, 12).fixedPrice;
        fixedPrice13 = get(configs, 13).fixedPrice;
        fixedPrice14 = get(configs, 14).fixedPrice;
        // fixedPrice15 = get(configs, 15).fixedPrice;
        // fixedPrice16 = get(configs, 16).fixedPrice;
        // fixedPrice17 = get(configs, 17).fixedPrice;
        // fixedPrice18 = get(configs, 18).fixedPrice;
        // fixedPrice19 = get(configs, 19).fixedPrice;
        // fixedPrice20 = get(configs, 20).fixedPrice;
        // fixedPrice21 = get(configs, 21).fixedPrice;
        // fixedPrice22 = get(configs, 22).fixedPrice;
        // fixedPrice23 = get(configs, 23).fixedPrice;
        // fixedPrice24 = get(configs, 24).fixedPrice;
        // fixedPrice25 = get(configs, 25).fixedPrice;
        // fixedPrice26 = get(configs, 26).fixedPrice;
        // fixedPrice27 = get(configs, 27).fixedPrice;
        // fixedPrice28 = get(configs, 28).fixedPrice;
        // fixedPrice29 = get(configs, 29).fixedPrice;

        uniswapMarket00 = get(configs, 0).uniswapMarket;
        uniswapMarket01 = get(configs, 1).uniswapMarket;
        uniswapMarket02 = get(configs, 2).uniswapMarket;
        uniswapMarket03 = get(configs, 3).uniswapMarket;
        uniswapMarket04 = get(configs, 4).uniswapMarket;
        uniswapMarket05 = get(configs, 5).uniswapMarket;
        uniswapMarket06 = get(configs, 6).uniswapMarket;
        uniswapMarket07 = get(configs, 7).uniswapMarket;
        uniswapMarket08 = get(configs, 8).uniswapMarket;
        uniswapMarket09 = get(configs, 9).uniswapMarket;
        uniswapMarket10 = get(configs, 10).uniswapMarket;
        uniswapMarket11 = get(configs, 11).uniswapMarket;
        uniswapMarket12 = get(configs, 12).uniswapMarket;
        uniswapMarket13 = get(configs, 13).uniswapMarket;
        uniswapMarket14 = get(configs, 14).uniswapMarket;
        // uniswapMarket15 = get(configs, 15).uniswapMarket;
        // uniswapMarket16 = get(configs, 16).uniswapMarket;
        // uniswapMarket17 = get(configs, 17).uniswapMarket;
        // uniswapMarket18 = get(configs, 18).uniswapMarket;
        // uniswapMarket19 = get(configs, 19).uniswapMarket;
        // uniswapMarket20 = get(configs, 20).uniswapMarket;
        // uniswapMarket21 = get(configs, 21).uniswapMarket;
        // uniswapMarket22 = get(configs, 22).uniswapMarket;
        // uniswapMarket23 = get(configs, 23).uniswapMarket;
        // uniswapMarket24 = get(configs, 24).uniswapMarket;
        // uniswapMarket25 = get(configs, 25).uniswapMarket;
        // uniswapMarket26 = get(configs, 26).uniswapMarket;
        // uniswapMarket27 = get(configs, 27).uniswapMarket;
        // uniswapMarket28 = get(configs, 28).uniswapMarket;
        // uniswapMarket29 = get(configs, 29).uniswapMarket;

        isUniswapReversed00 = get(configs, 0).isUniswapReversed;
        isUniswapReversed01 = get(configs, 1).isUniswapReversed;
        isUniswapReversed02 = get(configs, 2).isUniswapReversed;
        isUniswapReversed03 = get(configs, 3).isUniswapReversed;
        isUniswapReversed04 = get(configs, 4).isUniswapReversed;
        isUniswapReversed05 = get(configs, 5).isUniswapReversed;
        isUniswapReversed06 = get(configs, 6).isUniswapReversed;
        isUniswapReversed07 = get(configs, 7).isUniswapReversed;
        isUniswapReversed08 = get(configs, 8).isUniswapReversed;
        isUniswapReversed09 = get(configs, 9).isUniswapReversed;
        isUniswapReversed10 = get(configs, 10).isUniswapReversed;
        isUniswapReversed11 = get(configs, 11).isUniswapReversed;
        isUniswapReversed12 = get(configs, 12).isUniswapReversed;
        isUniswapReversed13 = get(configs, 13).isUniswapReversed;
        isUniswapReversed14 = get(configs, 14).isUniswapReversed;
        // isUniswapReversed15 = get(configs, 15).isUniswapReversed;
        // isUniswapReversed16 = get(configs, 16).isUniswapReversed;
        // isUniswapReversed17 = get(configs, 17).isUniswapReversed;
        // isUniswapReversed18 = get(configs, 18).isUniswapReversed;
        // isUniswapReversed19 = get(configs, 19).isUniswapReversed;
        // isUniswapReversed20 = get(configs, 20).isUniswapReversed;
        // isUniswapReversed21 = get(configs, 21).isUniswapReversed;
        // isUniswapReversed22 = get(configs, 22).isUniswapReversed;
        // isUniswapReversed23 = get(configs, 23).isUniswapReversed;
        // isUniswapReversed24 = get(configs, 24).isUniswapReversed;
        // isUniswapReversed25 = get(configs, 25).isUniswapReversed;
        // isUniswapReversed26 = get(configs, 26).isUniswapReversed;
        // isUniswapReversed27 = get(configs, 27).isUniswapReversed;
        // isUniswapReversed28 = get(configs, 28).isUniswapReversed;
        // isUniswapReversed29 = get(configs, 29).isUniswapReversed;

        isDirectMarket00 = get(configs, 0).isDirectMarket;
        isDirectMarket01 = get(configs, 1).isDirectMarket;
        isDirectMarket02 = get(configs, 2).isDirectMarket;
        isDirectMarket03 = get(configs, 3).isDirectMarket;
        isDirectMarket04 = get(configs, 4).isDirectMarket;
        isDirectMarket05 = get(configs, 5).isDirectMarket;
        isDirectMarket06 = get(configs, 6).isDirectMarket;
        isDirectMarket07 = get(configs, 7).isDirectMarket;
        isDirectMarket08 = get(configs, 8).isDirectMarket;
        isDirectMarket09 = get(configs, 9).isDirectMarket;
        isDirectMarket10 = get(configs, 10).isDirectMarket;
        isDirectMarket11 = get(configs, 11).isDirectMarket;
        isDirectMarket12 = get(configs, 12).isDirectMarket;
        isDirectMarket13 = get(configs, 13).isDirectMarket;
        isDirectMarket14 = get(configs, 14).isDirectMarket;
        // isDirectMarket15 = get(configs, 15).isDirectMarket;
        // isDirectMarket16 = get(configs, 16).isDirectMarket;
        // isDirectMarket17 = get(configs, 17).isDirectMarket;
        // isDirectMarket18 = get(configs, 18).isDirectMarket;
        // isDirectMarket19 = get(configs, 19).isDirectMarket;
        // isDirectMarket20 = get(configs, 20).isDirectMarket;
        // isDirectMarket21 = get(configs, 21).isDirectMarket;
        // isDirectMarket22 = get(configs, 22).isDirectMarket;
        // isDirectMarket23 = get(configs, 23).isDirectMarket;
        // isDirectMarket24 = get(configs, 24).isDirectMarket;
        // isDirectMarket25 = get(configs, 25).isDirectMarket;
        // isDirectMarket26 = get(configs, 26).isDirectMarket;
        // isDirectMarket27 = get(configs, 27).isDirectMarket;
        // isDirectMarket28 = get(configs, 28).isDirectMarket;
        // isDirectMarket29 = get(configs, 29).isDirectMarket;

        priceScale00 = get(configs, 0).priceScale;
        priceScale01 = get(configs, 1).priceScale;
        priceScale02 = get(configs, 2).priceScale;
        priceScale03 = get(configs, 3).priceScale;
        priceScale04 = get(configs, 4).priceScale;
        priceScale05 = get(configs, 5).priceScale;
        priceScale06 = get(configs, 6).priceScale;
        priceScale07 = get(configs, 7).priceScale;
        priceScale08 = get(configs, 8).priceScale;
        priceScale09 = get(configs, 9).priceScale;
        priceScale10 = get(configs, 10).priceScale;
        priceScale11 = get(configs, 11).priceScale;
        priceScale12 = get(configs, 12).priceScale;
        priceScale13 = get(configs, 13).priceScale;
        priceScale14 = get(configs, 14).priceScale;
        
    }

    function get(TokenConfig[] memory configs, uint i) internal pure returns (TokenConfig memory) {
        if (i < configs.length)
            return configs[i];
        return TokenConfig({
            underlying: address(0),
            symbolHash: bytes32(0),
            baseUnit: uint256(0),
            priceSource: PriceSource(0),
            fixedPrice: uint256(0),
            uniswapMarket: address(0),
            isUniswapReversed: false,
            isDirectMarket: false,
            priceScale: uint256(0)
        });
    }

    function getUnderlyingIndex(address underlying) internal view returns (uint) {
        if (underlying == underlying00) return 0;
        if (underlying == underlying01) return 1;
        if (underlying == underlying02) return 2;
        if (underlying == underlying03) return 3;
        if (underlying == underlying04) return 4;
        if (underlying == underlying05) return 5;
        if (underlying == underlying06) return 6;
        if (underlying == underlying07) return 7;
        if (underlying == underlying08) return 8;
        if (underlying == underlying09) return 9;
        if (underlying == underlying10) return 10;
        if (underlying == underlying11) return 11;
        if (underlying == underlying12) return 12;
        if (underlying == underlying13) return 13;
        if (underlying == underlying14) return 14;
        // if (underlying == underlying15) return 15;
        // if (underlying == underlying16) return 16;
        // if (underlying == underlying17) return 17;
        // if (underlying == underlying18) return 18;
        // if (underlying == underlying19) return 19;
        // if (underlying == underlying20) return 20;
        // if (underlying == underlying21) return 21;
        // if (underlying == underlying22) return 22;
        // if (underlying == underlying23) return 23;
        // if (underlying == underlying24) return 24;
        // if (underlying == underlying25) return 25;
        // if (underlying == underlying26) return 26;
        // if (underlying == underlying27) return 27;
        // if (underlying == underlying28) return 28;
        // if (underlying == underlying29) return 29;

        return uint(-1);
    }

    function getSymbolHashIndex(bytes32 symbolHash) internal view returns (uint) {
        if (symbolHash == symbolHash00) return 0;
        if (symbolHash == symbolHash01) return 1;
        if (symbolHash == symbolHash02) return 2;
        if (symbolHash == symbolHash03) return 3;
        if (symbolHash == symbolHash04) return 4;
        if (symbolHash == symbolHash05) return 5;
        if (symbolHash == symbolHash06) return 6;
        if (symbolHash == symbolHash07) return 7;
        if (symbolHash == symbolHash08) return 8;
        if (symbolHash == symbolHash09) return 9;
        if (symbolHash == symbolHash10) return 10;
        if (symbolHash == symbolHash11) return 11;
        if (symbolHash == symbolHash12) return 12;
        if (symbolHash == symbolHash13) return 13;
        if (symbolHash == symbolHash14) return 14;
        // if (symbolHash == symbolHash15) return 15;
        // if (symbolHash == symbolHash16) return 16;
        // if (symbolHash == symbolHash17) return 17;
        // if (symbolHash == symbolHash18) return 18;
        // if (symbolHash == symbolHash19) return 19;
        // if (symbolHash == symbolHash20) return 20;
        // if (symbolHash == symbolHash21) return 21;
        // if (symbolHash == symbolHash22) return 22;
        // if (symbolHash == symbolHash23) return 23;
        // if (symbolHash == symbolHash24) return 24;
        // if (symbolHash == symbolHash25) return 25;
        // if (symbolHash == symbolHash26) return 26;
        // if (symbolHash == symbolHash27) return 27;
        // if (symbolHash == symbolHash28) return 28;
        // if (symbolHash == symbolHash29) return 29;

        return uint(-1);
    }

    /**
     * @notice Get the i-th config, according to the order they were passed in originally
     * @param i The index of the config to get
     * @return The config object
     */
    function getTokenConfig(uint i) public view returns (TokenConfig memory) {
        require(i < numTokens, "token config not found");

        if (i == 1) return TokenConfig({underlying: underlying01, symbolHash: symbolHash01, baseUnit: baseUnit01, priceSource: priceSource01, fixedPrice: fixedPrice01, uniswapMarket: uniswapMarket01, isUniswapReversed: isUniswapReversed01, isDirectMarket: isDirectMarket01, priceScale: priceScale01});
        if (i == 0) return TokenConfig({underlying: underlying00, symbolHash: symbolHash00, baseUnit: baseUnit00, priceSource: priceSource00, fixedPrice: fixedPrice00, uniswapMarket: uniswapMarket00, isUniswapReversed: isUniswapReversed00, isDirectMarket: isDirectMarket00, priceScale: priceScale00});
        if (i == 2) return TokenConfig({underlying: underlying02, symbolHash: symbolHash02, baseUnit: baseUnit02, priceSource: priceSource02, fixedPrice: fixedPrice02, uniswapMarket: uniswapMarket02, isUniswapReversed: isUniswapReversed02, isDirectMarket: isDirectMarket02, priceScale: priceScale02});
        if (i == 3) return TokenConfig({underlying: underlying03, symbolHash: symbolHash03, baseUnit: baseUnit03, priceSource: priceSource03, fixedPrice: fixedPrice03, uniswapMarket: uniswapMarket03, isUniswapReversed: isUniswapReversed03, isDirectMarket: isDirectMarket03, priceScale: priceScale03});
        if (i == 4) return TokenConfig({underlying: underlying04, symbolHash: symbolHash04, baseUnit: baseUnit04, priceSource: priceSource04, fixedPrice: fixedPrice04, uniswapMarket: uniswapMarket04, isUniswapReversed: isUniswapReversed04, isDirectMarket: isDirectMarket04, priceScale: priceScale04});
        if (i == 5) return TokenConfig({underlying: underlying05, symbolHash: symbolHash05, baseUnit: baseUnit05, priceSource: priceSource05, fixedPrice: fixedPrice05, uniswapMarket: uniswapMarket05, isUniswapReversed: isUniswapReversed05, isDirectMarket: isDirectMarket05, priceScale: priceScale05});
        if (i == 6) return TokenConfig({underlying: underlying06, symbolHash: symbolHash06, baseUnit: baseUnit06, priceSource: priceSource06, fixedPrice: fixedPrice06, uniswapMarket: uniswapMarket06, isUniswapReversed: isUniswapReversed06, isDirectMarket: isDirectMarket06, priceScale: priceScale06});
        if (i == 7) return TokenConfig({underlying: underlying07, symbolHash: symbolHash07, baseUnit: baseUnit07, priceSource: priceSource07, fixedPrice: fixedPrice07, uniswapMarket: uniswapMarket07, isUniswapReversed: isUniswapReversed07, isDirectMarket: isDirectMarket07, priceScale: priceScale07});
        if (i == 8) return TokenConfig({underlying: underlying08, symbolHash: symbolHash08, baseUnit: baseUnit08, priceSource: priceSource08, fixedPrice: fixedPrice08, uniswapMarket: uniswapMarket08, isUniswapReversed: isUniswapReversed08, isDirectMarket: isDirectMarket08, priceScale: priceScale08});
        if (i == 9) return TokenConfig({underlying: underlying09, symbolHash: symbolHash09, baseUnit: baseUnit09, priceSource: priceSource09, fixedPrice: fixedPrice09, uniswapMarket: uniswapMarket09, isUniswapReversed: isUniswapReversed09, isDirectMarket: isDirectMarket09, priceScale: priceScale09});

        if (i == 10) return TokenConfig({underlying: underlying10, symbolHash: symbolHash10, baseUnit: baseUnit10, priceSource: priceSource10, fixedPrice: fixedPrice10, uniswapMarket: uniswapMarket10, isUniswapReversed: isUniswapReversed10, isDirectMarket: isDirectMarket10, priceScale: priceScale10});
        if (i == 11) return TokenConfig({underlying: underlying11, symbolHash: symbolHash11, baseUnit: baseUnit11, priceSource: priceSource11, fixedPrice: fixedPrice11, uniswapMarket: uniswapMarket11, isUniswapReversed: isUniswapReversed11, isDirectMarket: isDirectMarket11, priceScale: priceScale11});
        if (i == 12) return TokenConfig({underlying: underlying12, symbolHash: symbolHash12, baseUnit: baseUnit12, priceSource: priceSource12, fixedPrice: fixedPrice12, uniswapMarket: uniswapMarket12, isUniswapReversed: isUniswapReversed12, isDirectMarket: isDirectMarket12, priceScale: priceScale12});
        if (i == 13) return TokenConfig({underlying: underlying13, symbolHash: symbolHash13, baseUnit: baseUnit13, priceSource: priceSource13, fixedPrice: fixedPrice13, uniswapMarket: uniswapMarket13, isUniswapReversed: isUniswapReversed13, isDirectMarket: isDirectMarket13, priceScale: priceScale13});
        if (i == 14) return TokenConfig({underlying: underlying14, symbolHash: symbolHash14, baseUnit: baseUnit14, priceSource: priceSource14, fixedPrice: fixedPrice14, uniswapMarket: uniswapMarket14, isUniswapReversed: isUniswapReversed14, isDirectMarket: isDirectMarket14, priceScale: priceScale14});
        // if (i == 15) return TokenConfig({underlying: underlying15, symbolHash: symbolHash15, baseUnit: baseUnit15, priceSource: priceSource15, fixedPrice: fixedPrice15, uniswapMarket: uniswapMarket15, isUniswapReversed: isUniswapReversed15, isDirectMarket: isDirectMarkets[i]});
        // if (i == 16) return TokenConfig({underlying: underlying16, symbolHash: symbolHash16, baseUnit: baseUnit16, priceSource: priceSource16, fixedPrice: fixedPrice16, uniswapMarket: uniswapMarket16, isUniswapReversed: isUniswapReversed16, isDirectMarket: isDirectMarkets[i]});
        // if (i == 17) return TokenConfig({underlying: underlying17, symbolHash: symbolHash17, baseUnit: baseUnit17, priceSource: priceSource17, fixedPrice: fixedPrice17, uniswapMarket: uniswapMarket17, isUniswapReversed: isUniswapReversed17, isDirectMarket: isDirectMarkets[i]});
        // if (i == 18) return TokenConfig({underlying: underlying18, symbolHash: symbolHash18, baseUnit: baseUnit18, priceSource: priceSource18, fixedPrice: fixedPrice18, uniswapMarket: uniswapMarket18, isUniswapReversed: isUniswapReversed18, isDirectMarket: isDirectMarkets[i]});
        // if (i == 19) return TokenConfig({underlying: underlying19, symbolHash: symbolHash19, baseUnit: baseUnit19, priceSource: priceSource19, fixedPrice: fixedPrice19, uniswapMarket: uniswapMarket19, isUniswapReversed: isUniswapReversed19, isDirectMarket: isDirectMarkets[i]});

        // if (i == 20) return TokenConfig({underlying: underlying20, symbolHash: symbolHash20, baseUnit: baseUnit20, priceSource: priceSource20, fixedPrice: fixedPrice20, uniswapMarket: uniswapMarket20, isUniswapReversed: isUniswapReversed20, isDirectMarket: isDirectMarkets[i]});
        // if (i == 21) return TokenConfig({underlying: underlying21, symbolHash: symbolHash21, baseUnit: baseUnit21, priceSource: priceSource21, fixedPrice: fixedPrice21, uniswapMarket: uniswapMarket21, isUniswapReversed: isUniswapReversed21, isDirectMarket: isDirectMarkets[i]});
        // if (i == 22) return TokenConfig({underlying: underlying22, symbolHash: symbolHash22, baseUnit: baseUnit22, priceSource: priceSource22, fixedPrice: fixedPrice22, uniswapMarket: uniswapMarket22, isUniswapReversed: isUniswapReversed22, isDirectMarket: isDirectMarkets[i]});
        // if (i == 23) return TokenConfig({underlying: underlying23, symbolHash: symbolHash23, baseUnit: baseUnit23, priceSource: priceSource23, fixedPrice: fixedPrice23, uniswapMarket: uniswapMarket23, isUniswapReversed: isUniswapReversed23, isDirectMarket: isDirectMarkets[i]});
        // if (i == 24) return TokenConfig({underlying: underlying24, symbolHash: symbolHash24, baseUnit: baseUnit24, priceSource: priceSource24, fixedPrice: fixedPrice24, uniswapMarket: uniswapMarket24, isUniswapReversed: isUniswapReversed24, isDirectMarket: isDirectMarkets[i]});
        // if (i == 25) return TokenConfig({underlying: underlying25, symbolHash: symbolHash25, baseUnit: baseUnit25, priceSource: priceSource25, fixedPrice: fixedPrice25, uniswapMarket: uniswapMarket25, isUniswapReversed: isUniswapReversed25, isDirectMarket: isDirectMarkets[i]});
        // if (i == 26) return TokenConfig({underlying: underlying26, symbolHash: symbolHash26, baseUnit: baseUnit26, priceSource: priceSource26, fixedPrice: fixedPrice26, uniswapMarket: uniswapMarket26, isUniswapReversed: isUniswapReversed26, isDirectMarket: isDirectMarkets[i]});
        // if (i == 27) return TokenConfig({underlying: underlying27, symbolHash: symbolHash27, baseUnit: baseUnit27, priceSource: priceSource27, fixedPrice: fixedPrice27, uniswapMarket: uniswapMarket27, isUniswapReversed: isUniswapReversed27, isDirectMarket: isDirectMarkets[i]});
        // if (i == 28) return TokenConfig({underlying: underlying28, symbolHash: symbolHash28, baseUnit: baseUnit28, priceSource: priceSource28, fixedPrice: fixedPrice28, uniswapMarket: uniswapMarket28, isUniswapReversed: isUniswapReversed28, isDirectMarket: isDirectMarkets[i]});
        // if (i == 29) return TokenConfig({underlying: underlying29, symbolHash: symbolHash29, baseUnit: baseUnit29, priceSource: priceSource29, fixedPrice: fixedPrice29, uniswapMarket: uniswapMarket29, isUniswapReversed: isUniswapReversed29, isDirectMarket: isDirectMarkets[i]});
    }

    /**
     * @notice Get the config for symbol
     * @param symbol The symbol of the config to get
     * @return The config object
     */
    function getTokenConfigBySymbol(string memory symbol) public view returns (TokenConfig memory) {
        return getTokenConfigBySymbolHash(keccak256(abi.encodePacked(symbol)));
    }

    /**
     * @notice Get the config for the symbolHash
     * @param symbolHash The keccack256 of the symbol of the config to get
     * @return The config object
     */
    function getTokenConfigBySymbolHash(bytes32 symbolHash) public view returns (TokenConfig memory) {
        uint index = getSymbolHashIndex(symbolHash);
        if (index != uint(-1)) {
            return getTokenConfig(index);
        }

        revert("token config by symbol hash not found");
    }

    /**
     * @notice Get the config for an underlying asset
     * @param underlying The address of the underlying asset of the config to get
     * @return The config object
     */
    function getTokenConfigByUnderlying(address underlying) public view returns (TokenConfig memory) {
        uint index = getUnderlyingIndex(underlying);
        if (index != uint(-1)) {
            return getTokenConfig(index);
        }

        revert("token config by underlying not found");
    }
}

File 4 of 5 : UniswapLib.sol
// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.7.6;

// Based on code from https://github.com/Uniswap/uniswap-v2-periphery

// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format))
library FixedPoint {
    // range: [0, 2**112 - 1]
    // resolution: 1 / 2**112
    struct uq112x112 {
        uint224 _x;
    }

    // returns a uq112x112 which represents the ratio of the numerator to the denominator
    // equivalent to encode(numerator).div(denominator)
    function fraction(uint112 numerator, uint112 denominator) internal pure returns (uq112x112 memory) {
        require(denominator > 0, "FixedPoint: DIV_BY_ZERO");
        return uq112x112((uint224(numerator) << 112) / denominator);
    }

    // decode a uq112x112 into a uint with 18 decimals of precision
    function decode112with18(uq112x112 memory self) internal pure returns (uint) {
        // we only have 256 - 224 = 32 bits to spare, so scaling up by ~60 bits is dangerous
        // instead, get close to:
        //  (x * 1e18) >> 112
        // without risk of overflowing, e.g.:
        //  (x) / 2 ** (112 - lg(1e18))
        return uint(self._x) / 5192296858534827;
    }
}

// library with helper methods for oracles that are concerned with computing average prices
library UniswapV2OracleLibrary {
    using FixedPoint for *;

    // helper function that returns the current block timestamp within the range of uint32, i.e. [0, 2**32 - 1]
    function currentBlockTimestamp() internal view returns (uint32) {
        return uint32(block.timestamp % 2 ** 32);
    }

    // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.
    function currentCumulativePrices(
        address pair
    ) internal view returns (uint price0Cumulative, uint price1Cumulative, uint32 blockTimestamp) {
        blockTimestamp = currentBlockTimestamp();
        price0Cumulative = IUniswapV2PairForStateReading(pair).price0CumulativeLast();
        price1Cumulative = IUniswapV2PairForStateReading(pair).price1CumulativeLast();

        // if time has elapsed since the last update on the pair, mock the accumulated price values
        (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast) = IUniswapV2PairForStateReading(pair).getReserves();
        if (blockTimestampLast != blockTimestamp) {
            // subtraction overflow is desired
            uint32 timeElapsed = blockTimestamp - blockTimestampLast;
            // addition overflow is desired
            // counterfactual
            price0Cumulative += uint(FixedPoint.fraction(reserve1, reserve0)._x) * timeElapsed;
            // counterfactual
            price1Cumulative += uint(FixedPoint.fraction(reserve0, reserve1)._x) * timeElapsed;
        }
    }
}

interface IUniswapV2PairForStateReading {
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
    function price0CumulativeLast() external view returns (uint);
    function price1CumulativeLast() external view returns (uint);
}

File 5 of 5 : OpenOracleData.sol
// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.7.6;
pragma experimental ABIEncoderV2;

/**
 * @title The Open Oracle Data Base Contract
 * @author Compound Labs, Inc.
 */
contract OpenOracleData {
    /**
     * @notice The event emitted when a source writes to its storage
     */
    //event Write(address indexed source, <Key> indexed key, string kind, uint64 timestamp, <Value> value);

    /**
     * @notice Write a bunch of signed datum to the authenticated storage mapping
     * @param message The payload containing the timestamp, and (key, value) pairs
     * @param signature The cryptographic signature of the message payload, authorizing the source to write
     * @return The keys that were written
     */
    //function put(bytes calldata message, bytes calldata signature) external returns (<Key> memory);

    /**
     * @notice Read a single key with a pre-defined type signature from an authenticated source
     * @param source The verifiable author of the data
     * @param key The selector for the value to return
     * @return The claimed Unix timestamp for the data and the encoded value (defaults to (0, 0x))
     */
    //function get(address source, <Key> key) external view returns (uint, <Value>);

    /**
     * @notice Recovers the source address which signed a message
     * @dev Comparing to a claimed address would add nothing,
     *  as the caller could simply perform the recover and claim that address.
     * @param message The data that was presumably signed
     * @param signature The fingerprint of the data + private key
     * @return The source address which signed the message, presumably
     */
    function source(bytes memory message, bytes memory signature) public view returns (address) {
        (bytes32 r, bytes32 s, uint8 v) = abi.decode(signature, (bytes32, bytes32, uint8));
        bytes32 hash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(message)));
        return ecrecover(hash, v, r, s);
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract OpenOraclePriceData","name":"priceData_","type":"address"},{"internalType":"address","name":"reporter_","type":"address"},{"internalType":"string","name":"referenceAssetSymbol_","type":"string"},{"internalType":"uint256","name":"usdBaseUnit_","type":"uint256"},{"internalType":"uint256","name":"anchorToleranceMantissa_","type":"uint256"},{"internalType":"uint256","name":"anchorPeriod_","type":"uint256"},{"internalType":"address","name":"registry_","type":"address"},{"components":[{"internalType":"address","name":"underlying","type":"address"},{"internalType":"bytes32","name":"symbolHash","type":"bytes32"},{"internalType":"uint256","name":"baseUnit","type":"uint256"},{"internalType":"enum UniswapConfig.PriceSource","name":"priceSource","type":"uint8"},{"internalType":"uint256","name":"fixedPrice","type":"uint256"},{"internalType":"address","name":"uniswapMarket","type":"address"},{"internalType":"bool","name":"isUniswapReversed","type":"bool"},{"internalType":"bool","name":"isDirectMarket","type":"bool"},{"internalType":"uint256","name":"priceScale","type":"uint256"}],"internalType":"struct UniswapConfig.TokenConfig[]","name":"configs","type":"tuple[]"},{"internalType":"string[]","name":"_autoPokingSymbols","type":"string[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"symbol","type":"string"},{"indexed":false,"internalType":"uint256","name":"anchorPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTimestamp","type":"uint256"}],"name":"AnchorPriceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"symbol","type":"string"},{"indexed":false,"internalType":"uint256","name":"reporter","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"anchor","type":"uint256"}],"name":"PriceGuarded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"symbol","type":"string"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"PriceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"reporter","type":"address"}],"name":"ReporterInvalidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"symbolHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"oldTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"UniswapWindowUpdated","type":"event"},{"inputs":[],"name":"anchorPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"autoPokingSymbols","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ethBaseUnit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"expScale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string[]","name":"symbols","type":"string[]"}],"name":"freshenPrices","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"freshensAllPrices","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllAutoPokingSymbols","outputs":[{"internalType":"string[]","name":"","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"getAssetPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"getAssetPriceUpdateTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"i","type":"uint256"}],"name":"getTokenConfig","outputs":[{"components":[{"internalType":"address","name":"underlying","type":"address"},{"internalType":"bytes32","name":"symbolHash","type":"bytes32"},{"internalType":"uint256","name":"baseUnit","type":"uint256"},{"internalType":"enum UniswapConfig.PriceSource","name":"priceSource","type":"uint8"},{"internalType":"uint256","name":"fixedPrice","type":"uint256"},{"internalType":"address","name":"uniswapMarket","type":"address"},{"internalType":"bool","name":"isUniswapReversed","type":"bool"},{"internalType":"bool","name":"isDirectMarket","type":"bool"},{"internalType":"uint256","name":"priceScale","type":"uint256"}],"internalType":"struct UniswapConfig.TokenConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"symbol","type":"string"}],"name":"getTokenConfigBySymbol","outputs":[{"components":[{"internalType":"address","name":"underlying","type":"address"},{"internalType":"bytes32","name":"symbolHash","type":"bytes32"},{"internalType":"uint256","name":"baseUnit","type":"uint256"},{"internalType":"enum UniswapConfig.PriceSource","name":"priceSource","type":"uint8"},{"internalType":"uint256","name":"fixedPrice","type":"uint256"},{"internalType":"address","name":"uniswapMarket","type":"address"},{"internalType":"bool","name":"isUniswapReversed","type":"bool"},{"internalType":"bool","name":"isDirectMarket","type":"bool"},{"internalType":"uint256","name":"priceScale","type":"uint256"}],"internalType":"struct UniswapConfig.TokenConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"symbolHash","type":"bytes32"}],"name":"getTokenConfigBySymbolHash","outputs":[{"components":[{"internalType":"address","name":"underlying","type":"address"},{"internalType":"bytes32","name":"symbolHash","type":"bytes32"},{"internalType":"uint256","name":"baseUnit","type":"uint256"},{"internalType":"enum UniswapConfig.PriceSource","name":"priceSource","type":"uint8"},{"internalType":"uint256","name":"fixedPrice","type":"uint256"},{"internalType":"address","name":"uniswapMarket","type":"address"},{"internalType":"bool","name":"isUniswapReversed","type":"bool"},{"internalType":"bool","name":"isDirectMarket","type":"bool"},{"internalType":"uint256","name":"priceScale","type":"uint256"}],"internalType":"struct UniswapConfig.TokenConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"underlying","type":"address"}],"name":"getTokenConfigByUnderlying","outputs":[{"components":[{"internalType":"address","name":"underlying","type":"address"},{"internalType":"bytes32","name":"symbolHash","type":"bytes32"},{"internalType":"uint256","name":"baseUnit","type":"uint256"},{"internalType":"enum UniswapConfig.PriceSource","name":"priceSource","type":"uint8"},{"internalType":"uint256","name":"fixedPrice","type":"uint256"},{"internalType":"address","name":"uniswapMarket","type":"address"},{"internalType":"bool","name":"isUniswapReversed","type":"bool"},{"internalType":"bool","name":"isDirectMarket","type":"bool"},{"internalType":"uint256","name":"priceScale","type":"uint256"}],"internalType":"struct UniswapConfig.TokenConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"cToken","type":"address"}],"name":"getUnderlyingPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"cToken","type":"address"}],"name":"getUnderlyingPriceUpdateTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"message","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"invalidateReporter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lowerBoundAnchorRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"newObservations","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"acc","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"oldObservations","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"acc","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"messages","type":"bytes[]"},{"internalType":"bytes[]","name":"signatures","type":"bytes[]"},{"internalType":"string[]","name":"symbols","type":"string[]"}],"name":"postPrices","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"symbol","type":"string"}],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceData","outputs":[{"internalType":"contract OpenOraclePriceData","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"prices","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"pricesLastUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referenceAssetHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referenceAssetSymbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reporter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reporterInvalidated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"message","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"source","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"upperBoundAnchorRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"usdBaseUnit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

6112206040523480156200001257600080fd5b5060405162006bf638038062006bf683398101604081905262000035916200197c565b81600f81511115620000645760405162461bcd60e51b81526004016200005b9062001bab565b60405180910390fd5b805160805262000076816000620011f5565b5160601b6001600160601b03191660a05262000094816001620011f5565b5160601b6001600160601b03191660c052620000b2816002620011f5565b5160601b6001600160601b03191660e052620000d0816003620011f5565b5160601b6001600160601b03191661010052620000ef816004620011f5565b5160601b6001600160601b031916610120526200010e816005620011f5565b5160601b6001600160601b031916610140526200012d816006620011f5565b5160601b6001600160601b031916610160526200014c816007620011f5565b5160601b6001600160601b031916610180526200016b816008620011f5565b5160601b6001600160601b0319166101a0526200018a816009620011f5565b5160601b6001600160601b0319166101c052620001a981600a620011f5565b5160601b6001600160601b0319166101e052620001c881600b620011f5565b5160601b6001600160601b03191661020052620001e781600c620011f5565b5160601b6001600160601b031916610220526200020681600d620011f5565b5160601b6001600160601b031916610240526200022581600e620011f5565b5160601b6001600160601b0319166102605262000244816000620011f5565b602001516102805262000259816001620011f5565b602001516102a0526200026e816002620011f5565b602001516102c05262000283816003620011f5565b602001516102e05262000298816004620011f5565b6020015161030052620002ad816005620011f5565b6020015161032052620002c2816006620011f5565b6020015161034052620002d7816007620011f5565b6020015161036052620002ec816008620011f5565b602001516103805262000301816009620011f5565b602001516103a0526200031681600a620011f5565b602001516103c0526200032b81600b620011f5565b602001516103e0526200034081600c620011f5565b60200151610400526200035581600d620011f5565b60200151610420526200036a81600e620011f5565b60200151610440526200037f816000620011f5565b604001516104605262000394816001620011f5565b6040015161048052620003a9816002620011f5565b604001516104a052620003be816003620011f5565b604001516104c052620003d3816004620011f5565b604001516104e052620003e8816005620011f5565b6040015161050052620003fd816006620011f5565b604001516105205262000412816007620011f5565b604001516105405262000427816008620011f5565b60400151610560526200043c816009620011f5565b60400151610580526200045181600a620011f5565b604001516105a0526200046681600b620011f5565b604001516105c0526200047b81600c620011f5565b604001516105e0526200049081600d620011f5565b6040015161060052620004a581600e620011f5565b6040015161062052620004ba816000620011f5565b606001516005811115620004ca57fe5b610640816005811115620004da57fe5b60f81b905250620004ed816001620011f5565b606001516005811115620004fd57fe5b6106608160058111156200050d57fe5b60f81b90525062000520816002620011f5565b6060015160058111156200053057fe5b6106808160058111156200054057fe5b60f81b90525062000553816003620011f5565b6060015160058111156200056357fe5b6106a08160058111156200057357fe5b60f81b90525062000586816004620011f5565b6060015160058111156200059657fe5b6106c0816005811115620005a657fe5b60f81b905250620005b9816005620011f5565b606001516005811115620005c957fe5b6106e0816005811115620005d957fe5b60f81b905250620005ec816006620011f5565b606001516005811115620005fc57fe5b6107008160058111156200060c57fe5b60f81b9052506200061f816007620011f5565b6060015160058111156200062f57fe5b6107208160058111156200063f57fe5b60f81b90525062000652816008620011f5565b6060015160058111156200066257fe5b6107408160058111156200067257fe5b60f81b90525062000685816009620011f5565b6060015160058111156200069557fe5b610760816005811115620006a557fe5b60f81b905250620006b881600a620011f5565b606001516005811115620006c857fe5b610780816005811115620006d857fe5b60f81b905250620006eb81600b620011f5565b606001516005811115620006fb57fe5b6107a08160058111156200070b57fe5b60f81b9052506200071e81600c620011f5565b6060015160058111156200072e57fe5b6107c08160058111156200073e57fe5b60f81b9052506200075181600d620011f5565b6060015160058111156200076157fe5b6107e08160058111156200077157fe5b60f81b9052506200078481600e620011f5565b6060015160058111156200079457fe5b610800816005811115620007a457fe5b60f81b905250620007b7816000620011f5565b6080015161082052620007cc816001620011f5565b6080015161084052620007e1816002620011f5565b6080015161086052620007f6816003620011f5565b60800151610880526200080b816004620011f5565b608001516108a05262000820816005620011f5565b608001516108c05262000835816006620011f5565b608001516108e0526200084a816007620011f5565b60800151610900526200085f816008620011f5565b608001516109205262000874816009620011f5565b60800151610940526200088981600a620011f5565b60800151610960526200089e81600b620011f5565b6080015161098052620008b381600c620011f5565b608001516109a052620008c881600d620011f5565b608001516109c052620008dd81600e620011f5565b608001516109e052620008f2816000620011f5565b60a0015160601b6001600160601b031916610a005262000914816001620011f5565b60a0015160601b6001600160601b031916610a205262000936816002620011f5565b60a0015160601b6001600160601b031916610a405262000958816003620011f5565b60a0015160601b6001600160601b031916610a60526200097a816004620011f5565b60a0015160601b6001600160601b031916610a80526200099c816005620011f5565b60a0015160601b6001600160601b031916610aa052620009be816006620011f5565b60a0015160601b6001600160601b031916610ac052620009e0816007620011f5565b60a0015160601b6001600160601b031916610ae05262000a02816008620011f5565b60a0015160601b6001600160601b031916610b005262000a24816009620011f5565b60a0015160601b6001600160601b031916610b205262000a4681600a620011f5565b60a0015160601b6001600160601b031916610b405262000a6881600b620011f5565b60a0015160601b6001600160601b031916610b605262000a8a81600c620011f5565b60a0015160601b6001600160601b031916610b805262000aac81600d620011f5565b60a0015160601b6001600160601b031916610ba05262000ace81600e620011f5565b60a0015160601b6001600160601b031916610bc05262000af0816000620011f5565b60c00151151560f81b610be05262000b0a816001620011f5565b60c00151151560f81b610c005262000b24816002620011f5565b60c00151151560f81b610c205262000b3e816003620011f5565b60c00151151560f81b610c405262000b58816004620011f5565b60c00151151560f81b610c605262000b72816005620011f5565b60c00151151560f81b610c805262000b8c816006620011f5565b60c00151151560f81b610ca05262000ba6816007620011f5565b60c00151151560f81b610cc05262000bc0816008620011f5565b60c00151151560f81b610ce05262000bda816009620011f5565b60c00151151560f81b610d005262000bf481600a620011f5565b60c00151151560f81b610d205262000c0e81600b620011f5565b60c00151151560f81b610d405262000c2881600c620011f5565b60c00151151560f81b610d605262000c4281600d620011f5565b60c00151151560f81b610d805262000c5c81600e620011f5565b60c00151151560f81b610da05262000c76816000620011f5565b60e00151151560f81b610dc05262000c90816001620011f5565b60e00151151560f81b610de05262000caa816002620011f5565b60e00151151560f81b610e005262000cc4816003620011f5565b60e00151151560f81b610e205262000cde816004620011f5565b60e00151151560f81b610e405262000cf8816005620011f5565b60e00151151560f81b610e605262000d12816006620011f5565b60e00151151560f81b610e805262000d2c816007620011f5565b60e00151151560f81b610ea05262000d46816008620011f5565b60e00151151560f81b610ec05262000d60816009620011f5565b60e00151151560f81b610ee05262000d7a81600a620011f5565b60e00151151560f81b610f005262000d9481600b620011f5565b60e00151151560f81b610f205262000dae81600c620011f5565b60e00151151560f81b610f405262000dc881600d620011f5565b60e00151151560f81b610f605262000de281600e620011f5565b60e00151151560f81b610f805262000dfc816000620011f5565b6101000151610fa05262000e12816001620011f5565b6101000151610fc05262000e28816002620011f5565b6101000151610fe05262000e3e816003620011f5565b61010001516110005262000e54816004620011f5565b61010001516110205262000e6a816005620011f5565b61010001516110405262000e80816006620011f5565b61010001516110605262000e96816007620011f5565b61010001516110805262000eac816008620011f5565b61010001516110a05262000ec2816009620011f5565b61010001516110c05262000ed881600a620011f5565b61010001516110e05262000eee81600b620011f5565b61010001516111005262000f0481600c620011f5565b61010001516111205262000f1a81600d620011f5565b61010001516111405262000f3081600e620011f5565b610100015161116052506001600160601b031960608a811b82166111805289901b166111a052611200849052600a80546001600160a01b0385166001600160a01b0319909116179055805162000f8e9060019060208401906200156a565b50865162000fa49060079060208a0190620015ce565b50600760405160200162000fb9919062001a60565b60408051601f1981840301815291905280516020909101206008556009869055670de0b6b3a764000019851162000ffb5784670de0b6b3a76400000162000fff565b6000195b6111c052670de0b6b3a764000085106200101b57600162001027565b84670de0b6b3a7640000035b6111e05260005b8251811015620011e55760008382815181106200104757fe5b602002602001015190506000816040015111620010785760405162461bcd60e51b81526004016200005b9062001b26565b60a08101516002826060015160058111156200109057fe5b1480620010ad5750600382606001516005811115620010ab57fe5b145b1562001168576001600160a01b038116620010dc5760405162461bcd60e51b81526004016200005b9062001b68565b60208201516000620010ee8462001277565b600083815260056020908152604080832042808255600690935292819020828155600193840185905592909201839055905191925083917fe37d39315e3419c0937360f1ac88f2c52ecf67e3b22b367f82047ddb4591904a91620011589181908690819062001c1b565b60405180910390a2505062001192565b6001600160a01b03811615620011925760405162461bcd60e51b81526004016200005b9062001bd5565b81606001516005811115620011a357fe5b6005141580620011bb57506001600160a01b03861615155b620011da5760405162461bcd60e51b81526004016200005b9062001ad6565b50506001016200102e565b5050505050505050505062001c78565b620011ff6200165f565b825182101562001226578282815181106200121657fe5b6020026020010151905062001271565b506040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101919091525b92915050565b6000806000620012968460a00151620012b960201b620026a71760201c565b50915091508360c0015115620012b0579150620012b49050565b5090505b919050565b60008080620012c7620014b3565b9050836001600160a01b0316635909c0d56040518163ffffffff1660e01b815260040160206040518083038186803b1580156200130357600080fd5b505afa15801562001318573d6000803e3d6000fd5b505050506040513d60208110156200132f57600080fd5b505160408051635a3d549360e01b815290519194506001600160a01b03861691635a3d549391600480820192602092909190829003018186803b1580156200137657600080fd5b505afa1580156200138b573d6000803e3d6000fd5b505050506040513d6020811015620013a257600080fd5b505160408051630240bc6b60e21b81529051919350600091829182916001600160a01b03891691630902f1ac916004808301926060929190829003018186803b158015620013ef57600080fd5b505afa15801562001404573d6000803e3d6000fd5b505050506040513d60608110156200141b57600080fd5b5080516020820151604090920151909450909250905063ffffffff80821690851614620014a957600081850390508063ffffffff16620014678486620014bd60201b620028761760201c565b600001516001600160e01b031602870196508063ffffffff16620014978585620014bd60201b620028761760201c565b516001600160e01b0316029590950194505b5050509193909250565b63ffffffff421690565b620014c7620016ab565b6000826001600160701b03161162001526576040805162461bcd60e51b815260206004820152601760248201527f4669786564506f696e743a204449565f42595f5a45524f000000000000000000604482015290519081900360640190fd5b6040805160208101909152806001600160701b038416600160701b600160e01b03607087901b16816200155557fe5b046001600160e01b0316815250905092915050565b828054828255906000526020600020908101928215620015bc579160200282015b82811115620015bc5782518051620015ab918491602090910190620015ce565b50916020019190600101906200158b565b50620015ca929150620016bd565b5090565b828054600181600116156101000203166002900490600052602060002090601f01602090048101928262001606576000855562001651565b82601f106200162157805160ff191683800117855562001651565b8280016001018555821562001651579182015b828111156200165157825182559160200191906001019062001634565b50620015ca929150620016de565b6040805161012081018252600080825260208201819052918101829052906060820190815260006020820181905260408201819052606082018190526080820181905260a09091015290565b60408051602081019091526000815290565b80821115620015ca576000620016d48282620016f5565b50600101620016bd565b5b80821115620015ca5760008155600101620016df565b50805460018160011615610100020316600290046000825580601f106200171d57506200173d565b601f0160209004906000526020600020908101906200173d9190620016de565b50565b80516001600160a01b0381168114620012b457600080fd5b600082601f83011262001769578081fd5b81516020620017826200177c8362001c5a565b62001c36565b82815281810190858301855b85811015620017bb57620017a8898684518b0101620018f3565b845292840192908401906001016200178e565b5090979650505050505050565b600082601f830112620017d9578081fd5b81516020620017ec6200177c8362001c5a565b82815281810190858301610120808602880185018910156200180c578687fd5b865b86811015620018c45781838b03121562001826578788fd5b620018318262001c36565b6200183c8462001740565b815283870151878201526040808501519082015260606200185f818601620018e3565b908201526080848101519082015260a06200187c81860162001740565b9082015260c06200188f858201620018d2565b9082015260e0620018a2858201620018d2565b908201526101008481015190820152855293850193918101916001016200180e565b509198975050505050505050565b80518015158114620012b457600080fd5b805160068110620012b457600080fd5b600082601f83011262001904578081fd5b81516001600160401b038111156200191857fe5b60206200192e601f8301601f1916820162001c36565b828152858284870101111562001942578384fd5b835b838110156200196157858101830151828201840152820162001944565b838111156200197257848385840101525b5095945050505050565b60008060008060008060008060006101208a8c0312156200199b578485fd5b620019a68a62001740565b9850620019b660208b0162001740565b60408b01519098506001600160401b0380821115620019d3578687fd5b620019e18d838e01620018f3565b985060608c0151975060808c0151965060a08c0151955062001a0660c08d0162001740565b945060e08c015191508082111562001a1c578384fd5b62001a2a8d838e01620017c8565b93506101008c015191508082111562001a41578283fd5b5062001a508c828d0162001758565b9150509295985092959850929598565b600080835460018082166000811462001a82576001811462001a9a5762001acb565b60ff198316865260028304607f168601935062001acb565b600283048786526020808720875b8381101562001ac35781548a82015290850190820162001aa8565b505050860193505b509195945050505050565b60208082526030908201527f5265676973747279206164647265737320726571756972656420666f7220757360408201526f1a5b99c81bdc9858db1948185cdcd95d60821b606082015260800190565b60208082526022908201527f62617365556e6974206d7573742062652067726561746572207468616e207a65604082015261726f60f01b606082015260800190565b60208082526023908201527f7265706f7274656420707269636573206d757374206861766520616e20616e636040820152623437b960e91b606082015260800190565b60208082526010908201526f746f6f206d616e7920636f6e6669677360801b604082015260600190565b60208082526026908201527f6f6e6c79207265706f7274656420707269636573207574696c697a6520616e2060408201526530b731b437b960d11b606082015260800190565b93845260208401929092526040830152606082015260800190565b6040518181016001600160401b038111828210171562001c5257fe5b604052919050565b60006001600160401b0382111562001c6e57fe5b5060209081020190565b60805160a05160601c60c05160601c60e05160601c6101005160601c6101205160601c6101405160601c6101605160601c6101805160601c6101a05160601c6101c05160601c6101e05160601c6102005160601c6102205160601c6102405160601c6102605160601c610280516102a0516102c0516102e05161030051610320516103405161036051610380516103a0516103c0516103e05161040051610420516104405161046051610480516104a0516104c0516104e05161050051610520516105405161056051610580516105a0516105c0516105e05161060051610620516106405160f81c6106605160f81c6106805160f81c6106a05160f81c6106c05160f81c6106e05160f81c6107005160f81c6107205160f81c6107405160f81c6107605160f81c6107805160f81c6107a05160f81c6107c05160f81c6107e05160f81c6108005160f81c610820516108405161086051610880516108a0516108c0516108e05161090051610920516109405161096051610980516109a0516109c0516109e051610a005160601c610a205160601c610a405160601c610a605160601c610a805160601c610aa05160601c610ac05160601c610ae05160601c610b005160601c610b205160601c610b405160601c610b605160601c610b805160601c610ba05160601c610bc05160601c610be05160f81c610c005160f81c610c205160f81c610c405160f81c610c605160f81c610c805160f81c610ca05160f81c610cc05160f81c610ce05160f81c610d005160f81c610d205160f81c610d405160f81c610d605160f81c610d805160f81c610da05160f81c610dc05160f81c610de05160f81c610e005160f81c610e205160f81c610e405160f81c610e605160f81c610e805160f81c610ea05160f81c610ec05160f81c610ee05160f81c610f005160f81c610f205160f81c610f405160f81c610f605160f81c610f805160f81c610fa051610fc051610fe05161100051611020516110405161106051611080516110a0516110c0516110e051611100516111205161114051611160516111805160601c6111a05160601c6111c0516111e05161120051614830620023c6600039806123f45280613b4e5250806121ff5280613a945250806104cd5280613a69525080610442528061211752806121a752806131615280613351528061358b5250806123cb52806124ec52806131345280613324528061355e52508061206a525080611ed9525080611d48525080611bb7525080611a265250806118955250806117045250806115735250806113e25250806112515250806110c0525080610f2f525080610d9e525080610a80525080610c0d525080612042525080611eb1525080611d20525080611b8f5250806119fe52508061186d5250806116dc52508061154b5250806113ba525080611229525080611098525080610f07525080610d76525080610a58525080610be552508061201a525080611e89525080611cf8525080611b675250806119d65250806118455250806116b4525080611523525080611392525080611201525080611070525080610edf525080610d4e525080610a30525080610bbd525080611feb525080611e5a525080611cc9525080611b385250806119a75250806118165250806116855250806114f45250806113635250806111d2525080611041525080610eb0525080610d1f525080610a01525080610b8e525080611fc5525080611e34525080611ca3525080611b125250806119815250806117f052508061165f5250806114ce52508061133d5250806111ac52508061101b525080610e8a525080610cf95250806109db525080610b68525080611f94525080611e03525080611c72525080611ae15250806119505250806117bf52508061162e52508061149d52508061130c52508061117b525080610fea525080610e59525080610cc85250806109aa525080610b37525080611f6e525080611ddd525080611c4c525080611abb52508061192a5250806117995250806116085250806114775250806112e6525080611155525080610fc4525080610e33525080610ca2525080610984525080610b11525080611f485280612bca525080611db75280612b9a525080611c265280612b6a525080611a955280612b3a5250806119045280612b0a5250806117735280612ada5250806115e25280612aaa5250806114515280612a7a5250806112c05280612a4a52508061112f5280612a1a525080610f9e52806129ea525080610e0d52806129ba525080610c7c528061298a52508061095e528061295a525080610aeb528061292a525080611f195280612fa1525080611d885280612f5f525080611bf75280612f1d525080611a665280612edb5250806118d55280612e995250806117445280612e575250806115b35280612e155250806114225280612dd35250806112915280612d915250806111005280612d4f525080610f6f5280612d0d525080610dde5280612ccb525080610c4d5280612c8952508061092f5280612c47525080610abc5280612c055250806108db52806121db52506148306000f3fe608060405234801561001057600080fd5b50600436106102065760003560e01c80638e499bcf1161011a578063db2bbd6f116100ad578063e9206d781161007c578063e9206d78146103ec578063eaa1c2ca146103f4578063ecc1e98414610407578063fc57d4df1461041a578063fe2c61981461042d57610206565b8063db2bbd6f146103b6578063e4aa9993146103c9578063e61a5fe4146103dc578063e8315742146103e457610206565b8063b3596f07116100e9578063b3596f0714610386578063ce86644514610399578063d1b353b41461031b578063d7ee61d4146103a157610206565b80638e499bcf1461035b57806392b843571461036357806393329b521461036b578063b1d191a71461037e57610206565b80635525acdf1161019d57806369aa3ac61161016c57806369aa3ac61461031b5780637b1039991461032357806388e0d70c1461032b5780638a003888146103355780638aba91b41461034857610206565b80635525acdf146102cb5780635f349660146102e057806360846bc6146102f3578063651ed7881461030657610206565b8063276c2cba116101d9578063276c2cba1461027157806337c0e12d14610284578063482a6193146102a55780634da21942146102b857610206565b8063010ec4411461020b578063153e2601146102295780631a125204146102495780632410520914610269575b600080fd5b610213610440565b6040516102209190614155565b60405180910390f35b61023c610237366004613eb6565b610464565b6040516102209190614292565b61025c610257366004613eb6565b610476565b604051610220919061464d565b61023c6104cb565b61025c61027f366004613f6b565b6104ef565b610297610292366004613eb6565b61052c565b6040516102209291906146d9565b6102136102b3366004613f0b565b610545565b61025c6102c6366004613daa565b6105f2565b6102d3610631565b6040516102209190614227565b61023c6102ee366004613daa565b610709565b61023c610301366004613eb6565b610784565b61030e610796565b6040516102209190614287565b61023c61079f565b6102136107ab565b6103336107ba565b005b61025c610343366004613eb6565b6108d1565b610333610356366004613f0b565b612093565b61023c6121d9565b61023c6121fd565b61023c610379366004613daa565b612221565b61023c61222c565b61023c610394366004613daa565b612232565b61023c61223d565b6103a9612243565b60405161022091906142eb565b6103a96103c4366004613eb6565b6122d1565b6103336103d7366004613e77565b612347565b6102136123c9565b61023c6123ed565b61023c6123f2565b610297610402366004613eb6565b612416565b610333610415366004613de2565b61242f565b61023c610428366004613daa565b61260e565b61023c61043b366004613f6b565b612689565b7f000000000000000000000000000000000000000000000000000000000000000081565b60036020526000908152604090205481565b61047e613c5c565b600061048983612926565b905060001981146104a55761049d816108d1565b9150506104c6565b60405162461bcd60e51b81526004016104bd90614374565b60405180910390fd5b919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6104f7613c5c565b6105268260405160200161050b91906140e7565b60405160208183030381529060405280519060200120610476565b92915050565b6005602052600090815260409020805460019091015482565b6000806000808480602001905181019061055f9190613ece565b9250925092506000868051906020012060405160200161057f9190614103565b604051602081830303815290604052805190602001209050600181838686604051600081526020016040526040516105ba949392919061429b565b6020604051602081039080840390855afa1580156105dc573d6000803e3d6000fd5b5050604051601f19015198975050505050505050565b6105fa613c5c565b600061060583612c01565b905060001981146106195761049d816108d1565b60405162461bcd60e51b81526004016104bd9061450e565b60606001805480602002602001604051908101604052809291908181526020016000905b828210156107005760008481526020908190208301805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156106ec5780601f106106c1576101008083540402835291602001916106ec565b820191906000526020600020905b8154815290600101906020018083116106cf57829003601f168201915b505050505081526020019060010190610655565b50505050905090565b6000610526826001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b15801561074757600080fd5b505afa15801561075b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077f9190613dc6565b612fe1565b60026020526000908152604090205481565b60045460ff1681565b670de0b6b3a764000081565b600a546001600160a01b031681565b60006001805480602002602001604051908101604052809291908181526020016000905b828210156108895760008481526020908190208301805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156108755780601f1061084a57610100808354040283529160200191610875565b820191906000526020600020905b81548152906001019060200180831161085857829003601f168201915b5050505050815260200190600101906107de565b5050505090506000610899613010565b905060005b82518110156108cc576108c48382815181106108b657fe5b60200260200101518361320b565b60010161089e565b505050565b6108d9613c5c565b7f000000000000000000000000000000000000000000000000000000000000000082106109185760405162461bcd60e51b81526004016104bd9061448e565b8160011415610aa9576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000060058111156109d457fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b81610c36576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006005811115610b6157fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b8160021415610dc7576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006005811115610cf257fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b8160031415610f58576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006005811115610e8357fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b81600414156110e9576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000600581111561101457fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b816005141561127a576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000060058111156111a557fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b816006141561140b576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000600581111561133657fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b816007141561159c576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000060058111156114c757fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b816008141561172d576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000600581111561165857fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b81600914156118be576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000060058111156117e957fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b81600a1415611a4f576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000600581111561197a57fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b81600b1415611be0576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006005811115611b0b57fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b81600c1415611d71576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006005811115611c9c57fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b81600d1415611f02576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006005811115611e2d57fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b81600e14156104c6576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006005811115611fbe57fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b6000828060200190518101906120a99190613fe2565b5090506040516020016120bb90614134565b60405160208183030381529060405280519060200120816040516020016120e291906140e7565b60405160208183030381529060405280519060200120146121155760405162461bcd60e51b81526004016104bd90614589565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166121498484610545565b6001600160a01b03161461216f5760405162461bcd60e51b81526004016104bd906144be565b6004805460ff191660011790556040517f98a13f7b181a3a1f99c871e7a3507d4a037d386d157279f978e0d555ae9fe74d906121cc907f000000000000000000000000000000000000000000000000000000000000000090614155565b60405180910390a1505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600061052682612fe1565b60085481565b6000610526826136b1565b60095481565b6007805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156122c95780601f1061229e576101008083540402835291602001916122c9565b820191906000526020600020905b8154815290600101906020018083116122ac57829003601f168201915b505050505081565b600181815481106122e157600080fd5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152935090918301828280156122c95780601f1061229e576101008083540402835291602001916122c9565b6000612351613010565b905060005b828110156123c3576123bb84848381811061236d57fe5b905060200281019061237f9190614702565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525086925061320b915050565b600101612356565b50505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600f81565b7f000000000000000000000000000000000000000000000000000000000000000081565b6006602052600090815260409020805460019091015482565b84831461244e5760405162461bcd60e51b81526004016104bd9061460a565b60005b858110156125d55760006124b684848481811061246a57fe5b905060200281019061247c9190614702565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506104ef92505050565b90506002816060015160058111156124ca57fe5b14806124e557506004816060015160058111156124e357fe5b145b156125cc577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166338636e9a89898581811061252557fe5b90506020028101906125379190614702565b89898781811061254357fe5b90506020028101906125559190614702565b6040518563ffffffff1660e01b815260040161257494939291906142b9565b600060405180830381600087803b15801561258e57600080fd5b505af11580156125a2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526125ca9190810190613fb0565b505b50600101612451565b5060006125e0613010565b905060005b82811015612604576125fc84848381811061236d57fe5b6001016125e5565b5050505050505050565b6000610526826001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b15801561264c57600080fd5b505afa158015612660573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126849190613dc6565b6136b1565b600080612695836104ef565b90506126a0816136f9565b9392505050565b60008060006126b461383a565b9050836001600160a01b0316635909c0d56040518163ffffffff1660e01b815260040160206040518083038186803b1580156126ef57600080fd5b505afa158015612703573d6000803e3d6000fd5b505050506040513d602081101561271957600080fd5b505160408051635a3d549360e01b815290519194506001600160a01b03861691635a3d549391600480820192602092909190829003018186803b15801561275f57600080fd5b505afa158015612773573d6000803e3d6000fd5b505050506040513d602081101561278957600080fd5b505160408051630240bc6b60e21b81529051919350600091829182916001600160a01b03891691630902f1ac916004808301926060929190829003018186803b1580156127d557600080fd5b505afa1580156127e9573d6000803e3d6000fd5b505050506040513d60608110156127ff57600080fd5b5080516020820151604090920151909450909250905063ffffffff8082169085161461286c5780840363ffffffff81166128398486612876565b516001600160e01b031602969096019563ffffffff811661285a8585612876565b516001600160e01b0316029590950194505b5050509193909250565b61287e613ca8565b6000826001600160701b0316116128dc576040805162461bcd60e51b815260206004820152601760248201527f4669786564506f696e743a204449565f42595f5a45524f000000000000000000604482015290519081900360640190fd5b6040805160208101909152806001600160701b0384166dffffffffffffffffffffffffffff60701b607087901b168161291157fe5b046001600160e01b0316815250905092915050565b60007f0000000000000000000000000000000000000000000000000000000000000000821415612958575060006104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612988575060016104c6565b7f00000000000000000000000000000000000000000000000000000000000000008214156129b8575060026104c6565b7f00000000000000000000000000000000000000000000000000000000000000008214156129e8575060036104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612a18575060046104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612a48575060056104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612a78575060066104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612aa8575060076104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612ad8575060086104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612b08575060096104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612b385750600a6104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612b685750600b6104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612b985750600c6104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612bc85750600d6104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612bf85750600e6104c6565b50600019919050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612c45575060006104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612c87575060016104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612cc9575060026104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612d0b575060036104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612d4d575060046104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612d8f575060056104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612dd1575060066104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612e13575060076104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612e55575060086104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612e97575060096104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612ed95750600a6104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612f1b5750600b6104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612f5d5750600c6104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612f9f5750600d6104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612bf85750600e6104c6565b6000612feb613c5c565b612ff4836105f2565b6020908101516000908152600390915260409020549392505050565b6000806000613020600854610476565b90508060600151600581111561303257fe5b6002148061304f57508060600151600581111561304b57fe5b6003145b156130fc5760078054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526130f593909290918301828280156130e15780601f106130b6576101008083540402835291602001916130e1565b820191906000526020600020905b8154815290600101906020018083116130c457829003601f168201915b505050505082670de0b6b3a7640000613844565b91506131e8565b8060600151600581111561310c57fe5b6005141561311d576130f581613984565b604051633b4bbd1d60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906376977a3a9061318c907f00000000000000000000000000000000000000000000000000000000000000009060079060040161418d565b60206040518083038186803b1580156131a457600080fd5b505afa1580156131b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131dc9190614049565b6001600160401b031691505b816132055760405162461bcd60e51b81526004016104bd90614416565b50905090565b6000613216836104ef565b905060028160600151600581111561322a57fe5b1480613245575060038160600151600581111561324357fe5b145b8061325f575060048160600151600581111561325d57fe5b145b80613279575060058160600151600581111561327757fe5b145b6132955760405162461bcd60e51b81526004016104bd906143b9565b60405142906000906132ab9086906020016140e7565b6040516020818303038152906040528051906020012090508060085414156132f2576008805460009081526002602090815260408083208890559254825260039052208290555b60048360600151600581111561330457fe5b141561342a57604051633b4bbd1d60e11b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906376977a3a9061337b907f0000000000000000000000000000000000000000000000000000000000000000908a90600401614169565b60206040518083038186803b15801561339357600080fd5b505afa1580156133a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133cb9190614049565b60008381526002602090815260408083206001600160401b039490941693849055600390915290819020859055519091506000805160206147db8339815191529061341990889084906142fe565b60405180910390a1505050506136ad565b60058360600151600581111561343c57fe5b141561349857600061344d84613984565b6000838152600260209081526040808320849055600390915290819020859055519091506000805160206147db8339815191529061348e90889084906142fe565b60405180910390a1505b60006008548214156134ab5750836134d4565b60008460e001516134bc57856134c3565b8461010001515b90506134d0878683613844565b9150505b6003846060015160058111156134e657fe5b14806134f4575060045460ff165b15613544576000828152600260209081526040808320849055600390915290819020849055516000805160206147db8339815191529061353790889084906142fe565b60405180910390a16136a8565b604051633b4bbd1d60e11b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906376977a3a906135b5907f0000000000000000000000000000000000000000000000000000000000000000908b90600401614169565b60206040518083038186803b1580156135cd57600080fd5b505afa1580156135e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136059190614049565b6001600160401b0316905061361a8183613a40565b1561366a576000838152600260209081526040808320849055600390915290819020859055516000805160206147db8339815191529061365d90899084906142fe565b60405180910390a16136a6565b7f90756d4c8646a4591078abac0e4e32dfa8437921729e36d51b88b659d265bfde87828460405161369d93929190614320565b60405180910390a15b505b505050505b5050565b60006136bb613c5c565b6136c4836105f2565b905080604001516136ea6c0c9f2c9cd04674edea400000006136e5846136f9565b613ac8565b816136f157fe5b049392505050565b600060028260600151600581111561370d57fe5b1480613728575060038260600151600581111561372657fe5b145b80613742575060048260600151600581111561374057fe5b145b8061375c575060058260600151600581111561375a57fe5b145b1561377c57506020808201516000908152600290915260409020546104c6565b60018260600151600581111561378e57fe5b141561379f575060808101516104c6565b6000826060015160058111156137b157fe5b14156104c6576000600260006040516020016137cc90614146565b604051602081830303815290604052805190602001208152602001908152602001600020549050600081116138135760405162461bcd60e51b81526004016104bd906145be565b670de0b6b3a764000061382a828560800151613ac8565b8161383157fe5b049150506104c6565b63ffffffff421690565b60008060008061385386613b02565b9250925092508042116138785760405162461bcd60e51b81526004016104bd90614552565b6000814203905060006040518060200160405280838688038161389757fe5b046001600160e01b0316815250905060006138b182613c0e565b905060006138bf828a613ac8565b90506000670de0b6b3a7640000806138db848e60400151613ac8565b816138e257fe5b04816138ea57fe5b0490506008548c60405160200161390191906140e7565b6040516020818303038152906040528051906020012014156139385760095461392d82620f4240613ac8565b8161393457fe5b0490505b7ff63d078e0de851897107641e96093a59e5ddc3c25e7b85a2585e3eba9e774a7b8c82884260405161396d9493929190614345565b60405180910390a19b9a5050505050505050505050565b600a54815160405163775934ff60e11b81526000926001600160a01b03169163eeb269fe916139b69190600401614155565b60206040518083038186803b1580156139ce57600080fd5b505afa1580156139e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a069190614031565b9050613a1581620f4240613ac8565b9050613a25818360400151613ac8565b90506ec097ce7bc90715b34b9f1000000000815b0492915050565b60008215613abf57600083613a5d84670de0b6b3a7640000613ac8565b81613a6457fe5b0490507f00000000000000000000000000000000000000000000000000000000000000008111158015613ab757507f00000000000000000000000000000000000000000000000000000000000000008110155b915050610526565b50600092915050565b600082613ad757506000610526565b82820282848281613ae457fe5b04146126a05760405162461bcd60e51b81526004016104bd90614457565b600080600080846020015190506000613b1a86613c2a565b60008381526006602090815260409182902082518084019093528054808452600190910154918301919091529192509042037f00000000000000000000000000000000000000000000000000000000000000008110613be9578151600085815260056020908152604080832093845581860180516001958601556006835292819020428082559401879055908b015185519251915190937fe37d39315e3419c0937360f1ac88f2c52ecf67e3b22b367f82047ddb4591904a93613be093909289906146e7565b60405180910390a25b5050600091825260056020526040909120600181015490549196909550909350915050565b80516000906612725dd1d243ab906001600160e01b0316613a39565b6000806000613c3c8460a001516126a7565b50915091508360c0015115613c545791506104c69050565b5090506104c6565b6040805161012081018252600080825260208201819052918101829052906060820190815260006020820181905260408201819052606082018190526080820181905260a09091015290565b60408051602081019091526000815290565b6000613ccd613cc884614769565b614746565b9050828152838383011115613ce157600080fd5b828260208301376000602084830101529392505050565b60008083601f840112613d09578182fd5b5081356001600160401b03811115613d1f578182fd5b6020830191508360208083028501011115613d3957600080fd5b9250929050565b600082601f830112613d50578081fd5b6126a083833560208501613cba565b600082601f830112613d6f578081fd5b8151613d7d613cc882614769565b818152846020838601011115613d91578283fd5b613da2826020830160208701614796565b949350505050565b600060208284031215613dbb578081fd5b81356126a0816147c2565b600060208284031215613dd7578081fd5b81516126a0816147c2565b60008060008060008060608789031215613dfa578182fd5b86356001600160401b0380821115613e10578384fd5b613e1c8a838b01613cf8565b90985096506020890135915080821115613e34578384fd5b613e408a838b01613cf8565b90965094506040890135915080821115613e58578384fd5b50613e6589828a01613cf8565b979a9699509497509295939492505050565b60008060208385031215613e89578182fd5b82356001600160401b03811115613e9e578283fd5b613eaa85828601613cf8565b90969095509350505050565b600060208284031215613ec7578081fd5b5035919050565b600080600060608486031215613ee2578283fd5b8351925060208401519150604084015160ff81168114613f00578182fd5b809150509250925092565b60008060408385031215613f1d578182fd5b82356001600160401b0380821115613f33578384fd5b613f3f86838701613d40565b93506020850135915080821115613f54578283fd5b50613f6185828601613d40565b9150509250929050565b600060208284031215613f7c578081fd5b81356001600160401b03811115613f91578182fd5b8201601f81018413613fa1578182fd5b613da284823560208401613cba565b600060208284031215613fc1578081fd5b81516001600160401b03811115613fd6578182fd5b613da284828501613d5f565b60008060408385031215613ff4578081fd5b82516001600160401b03811115614009578182fd5b61401585828601613d5f565b9250506020830151614026816147c2565b809150509250929050565b600060208284031215614042578081fd5b5051919050565b60006020828403121561405a578081fd5b81516001600160401b03811681146126a0578182fd5b6001600160a01b03169052565b15159052565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600681106140b757fe5b9052565b600081518084526140d3816020860160208601614796565b601f01601f19169290920160200192915050565b600082516140f9818460208701614796565b9190910192915050565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b65726f7461746560d01b815260060190565b6208aa8960eb1b815260030190565b6001600160a01b0391909116815260200190565b6001600160a01b0383168152604060208201819052600090613da2908301846140bb565b60006040820160018060a01b038516835260206040818501528285546001808216600081146141c357600181146141e157614219565b60028304607f16865260ff1983166060890152608088019350614219565b600283048087526141f18a61478a565b885b8281101561420f5781548b8201606001529084019087016141f3565b8a01606001955050505b509198975050505050505050565b6000602080830181845280855180835260408601915060408482028701019250838701855b8281101561427a57603f198886030184526142688583516140bb565b9450928501929085019060010161424c565b5092979650505050505050565b901515815260200190565b90815260200190565b93845260ff9290921660208401526040830152606082015260800190565b6000604082526142cd604083018688614083565b82810360208401526142e0818587614083565b979650505050505050565b6000602082526126a060208301846140bb565b60006040825261431160408301856140bb565b90508260208301529392505050565b60006060825261433360608301866140bb565b60208301949094525060400152919050565b60006080825261435860808301876140bb565b6020830195909552506040810192909252606090910152919050565b60208082526025908201527f746f6b656e20636f6e6669672062792073796d626f6c2068617368206e6f7420604082015264199bdd5b9960da1b606082015260800190565b6020808252603f908201527f6f6e6c79207265706f727465722c20756e69737761702c206f7261636c65206f60408201527f72207369676e65642d6f6e6c79207072696365732067657420706f7374656400606082015260800190565b60208082526021908201527f5265666572656e636520617373657420707269636520756e617661696c61626c6040820152606560f81b606082015260800190565b60208082526017908201527f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000604082015260600190565b6020808252601690820152751d1bdad95b8818dbdb999a59c81b9bdd08199bdd5b9960521b604082015260600190565b60208082526030908201527f696e76616c69646174696f6e206d657373616765206d75737420636f6d65206660408201526f3937b6903a3432903932b837b93a32b960811b606082015260800190565b60208082526024908201527f746f6b656e20636f6e66696720627920756e6465726c79696e67206e6f7420666040820152631bdd5b9960e21b606082015260800190565b6020808252601a908201527f6e6f77206d75737420636f6d65206166746572206265666f7265000000000000604082015260600190565b6020808252818101527f696e76616c6964206d657373616765206d7573742062652027726f7461746527604082015260600190565b6020808252602c908201527f455448207072696365206e6f74207365742c2063616e6e6f7420636f6e76657260408201526b7420746f20646f6c6c61727360a01b606082015260800190565b60208082526023908201527f6d6573736167657320616e64207369676e617475726573206d75737420626520604082015262313a3160e81b606082015260800190565b81516001600160a01b031681526020808301519082015260408083015190820152606080830151610120830191614686908401826140ad565b506080830151608083015260a08301516146a360a0840182614070565b5060c08301516146b660c084018261407d565b5060e08301516146c960e084018261407d565b5061010092830151919092015290565b918252602082015260400190565b93845260208401929092526040830152606082015260800190565b6000808335601e19843603018112614718578283fd5b8301803591506001600160401b03821115614731578283fd5b602001915036819003821315613d3957600080fd5b6040518181016001600160401b038111828210171561476157fe5b604052919050565b60006001600160401b0382111561477c57fe5b50601f01601f191660200190565b60009081526020902090565b60005b838110156147b1578181015183820152602001614799565b838111156123c35750506000910152565b6001600160a01b03811681146147d757600080fd5b5056fe159e83f4712ba2552e68be9d848e49bf6dd35c24f19564ffd523b6549450a2f4a2646970667358221220657fd85446136f43dc5c1d46d16afc2b709f7aeec99f525410e6ac78a38f41df64736f6c63430007060033000000000000000000000000a61843f4ea67faa7816b928010c8ca360f76cc99000000000000000000000000fceadafab14d46e20144f48824d0c09b1a03f2bc000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000000000000000000002c68af0bb14000000000000000000000000000000000000000000000000000000000000000007080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000003c00000000000000000000000000000000000000000000000000000000000000004474c4d52000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeea4690066220620100ea0109a1e46cbd5096ab757e3117d17b6ee1b6f27fe420c0000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b929914b89584b4081c7966ac6287636f7efd053000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd3b51d98478d53f4515a306be565c6eebef1d586ecfd38039ec34885e5db2042e2d32737d0642a40a759e9d1076d51bccec8de90000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000099588867e817023162f4d4829995299054a5fc570000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102065760003560e01c80638e499bcf1161011a578063db2bbd6f116100ad578063e9206d781161007c578063e9206d78146103ec578063eaa1c2ca146103f4578063ecc1e98414610407578063fc57d4df1461041a578063fe2c61981461042d57610206565b8063db2bbd6f146103b6578063e4aa9993146103c9578063e61a5fe4146103dc578063e8315742146103e457610206565b8063b3596f07116100e9578063b3596f0714610386578063ce86644514610399578063d1b353b41461031b578063d7ee61d4146103a157610206565b80638e499bcf1461035b57806392b843571461036357806393329b521461036b578063b1d191a71461037e57610206565b80635525acdf1161019d57806369aa3ac61161016c57806369aa3ac61461031b5780637b1039991461032357806388e0d70c1461032b5780638a003888146103355780638aba91b41461034857610206565b80635525acdf146102cb5780635f349660146102e057806360846bc6146102f3578063651ed7881461030657610206565b8063276c2cba116101d9578063276c2cba1461027157806337c0e12d14610284578063482a6193146102a55780634da21942146102b857610206565b8063010ec4411461020b578063153e2601146102295780631a125204146102495780632410520914610269575b600080fd5b610213610440565b6040516102209190614155565b60405180910390f35b61023c610237366004613eb6565b610464565b6040516102209190614292565b61025c610257366004613eb6565b610476565b604051610220919061464d565b61023c6104cb565b61025c61027f366004613f6b565b6104ef565b610297610292366004613eb6565b61052c565b6040516102209291906146d9565b6102136102b3366004613f0b565b610545565b61025c6102c6366004613daa565b6105f2565b6102d3610631565b6040516102209190614227565b61023c6102ee366004613daa565b610709565b61023c610301366004613eb6565b610784565b61030e610796565b6040516102209190614287565b61023c61079f565b6102136107ab565b6103336107ba565b005b61025c610343366004613eb6565b6108d1565b610333610356366004613f0b565b612093565b61023c6121d9565b61023c6121fd565b61023c610379366004613daa565b612221565b61023c61222c565b61023c610394366004613daa565b612232565b61023c61223d565b6103a9612243565b60405161022091906142eb565b6103a96103c4366004613eb6565b6122d1565b6103336103d7366004613e77565b612347565b6102136123c9565b61023c6123ed565b61023c6123f2565b610297610402366004613eb6565b612416565b610333610415366004613de2565b61242f565b61023c610428366004613daa565b61260e565b61023c61043b366004613f6b565b612689565b7f000000000000000000000000fceadafab14d46e20144f48824d0c09b1a03f2bc81565b60036020526000908152604090205481565b61047e613c5c565b600061048983612926565b905060001981146104a55761049d816108d1565b9150506104c6565b60405162461bcd60e51b81526004016104bd90614374565b60405180910390fd5b919050565b7f00000000000000000000000000000000000000000000000010a741a46278000081565b6104f7613c5c565b6105268260405160200161050b91906140e7565b60405160208183030381529060405280519060200120610476565b92915050565b6005602052600090815260409020805460019091015482565b6000806000808480602001905181019061055f9190613ece565b9250925092506000868051906020012060405160200161057f9190614103565b604051602081830303815290604052805190602001209050600181838686604051600081526020016040526040516105ba949392919061429b565b6020604051602081039080840390855afa1580156105dc573d6000803e3d6000fd5b5050604051601f19015198975050505050505050565b6105fa613c5c565b600061060583612c01565b905060001981146106195761049d816108d1565b60405162461bcd60e51b81526004016104bd9061450e565b60606001805480602002602001604051908101604052809291908181526020016000905b828210156107005760008481526020908190208301805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156106ec5780601f106106c1576101008083540402835291602001916106ec565b820191906000526020600020905b8154815290600101906020018083116106cf57829003601f168201915b505050505081526020019060010190610655565b50505050905090565b6000610526826001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b15801561074757600080fd5b505afa15801561075b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077f9190613dc6565b612fe1565b60026020526000908152604090205481565b60045460ff1681565b670de0b6b3a764000081565b600a546001600160a01b031681565b60006001805480602002602001604051908101604052809291908181526020016000905b828210156108895760008481526020908190208301805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156108755780601f1061084a57610100808354040283529160200191610875565b820191906000526020600020905b81548152906001019060200180831161085857829003601f168201915b5050505050815260200190600101906107de565b5050505090506000610899613010565b905060005b82518110156108cc576108c48382815181106108b657fe5b60200260200101518361320b565b60010161089e565b505050565b6108d9613c5c565b7f000000000000000000000000000000000000000000000000000000000000000282106109185760405162461bcd60e51b81526004016104bd9061448e565b8160011415610aa9576040518061012001604052807f000000000000000000000000cd3b51d98478d53f4515a306be565c6eebef1d586001600160a01b031681526020017f6ecfd38039ec34885e5db2042e2d32737d0642a40a759e9d1076d51bccec8de981526020017f0000000000000000000000000000000000000000000000000de0b6b3a764000081526020017f000000000000000000000000000000000000000000000000000000000000000360058111156109d457fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000099588867e817023162f4d4829995299054a5fc576001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000001151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b81610c36576040518061012001604052807f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b031681526020017fa4690066220620100ea0109a1e46cbd5096ab757e3117d17b6ee1b6f27fe420c81526020017f0000000000000000000000000000000000000000000000000de0b6b3a764000081526020017f00000000000000000000000000000000000000000000000000000000000000036005811115610b6157fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000b929914b89584b4081c7966ac6287636f7efd0536001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000001151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b8160021415610dc7576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006005811115610cf257fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b8160031415610f58576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006005811115610e8357fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b81600414156110e9576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000600581111561101457fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b816005141561127a576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000060058111156111a557fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b816006141561140b576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000600581111561133657fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b816007141561159c576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000060058111156114c757fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b816008141561172d576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000600581111561165857fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b81600914156118be576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000060058111156117e957fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b81600a1415611a4f576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000600581111561197a57fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b81600b1415611be0576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006005811115611b0b57fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b81600c1415611d71576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006005811115611c9c57fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b81600d1415611f02576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006005811115611e2d57fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b81600e14156104c6576040518061012001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006005811115611fbe57fe5b81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f0000000000000000000000000000000000000000000000000000000000000000151581526020017f000000000000000000000000000000000000000000000000000000000000000081525090506104c6565b6000828060200190518101906120a99190613fe2565b5090506040516020016120bb90614134565b60405160208183030381529060405280519060200120816040516020016120e291906140e7565b60405160208183030381529060405280519060200120146121155760405162461bcd60e51b81526004016104bd90614589565b7f000000000000000000000000fceadafab14d46e20144f48824d0c09b1a03f2bc6001600160a01b03166121498484610545565b6001600160a01b03161461216f5760405162461bcd60e51b81526004016104bd906144be565b6004805460ff191660011790556040517f98a13f7b181a3a1f99c871e7a3507d4a037d386d157279f978e0d555ae9fe74d906121cc907f000000000000000000000000fceadafab14d46e20144f48824d0c09b1a03f2bc90614155565b60405180910390a1505050565b7f000000000000000000000000000000000000000000000000000000000000000281565b7f0000000000000000000000000000000000000000000000000b1a2bc2ec50000081565b600061052682612fe1565b60085481565b6000610526826136b1565b60095481565b6007805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156122c95780601f1061229e576101008083540402835291602001916122c9565b820191906000526020600020905b8154815290600101906020018083116122ac57829003601f168201915b505050505081565b600181815481106122e157600080fd5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152935090918301828280156122c95780601f1061229e576101008083540402835291602001916122c9565b6000612351613010565b905060005b828110156123c3576123bb84848381811061236d57fe5b905060200281019061237f9190614702565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525086925061320b915050565b600101612356565b50505050565b7f000000000000000000000000a61843f4ea67faa7816b928010c8ca360f76cc9981565b600f81565b7f000000000000000000000000000000000000000000000000000000000000070881565b6006602052600090815260409020805460019091015482565b84831461244e5760405162461bcd60e51b81526004016104bd9061460a565b60005b858110156125d55760006124b684848481811061246a57fe5b905060200281019061247c9190614702565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506104ef92505050565b90506002816060015160058111156124ca57fe5b14806124e557506004816060015160058111156124e357fe5b145b156125cc577f000000000000000000000000a61843f4ea67faa7816b928010c8ca360f76cc996001600160a01b03166338636e9a89898581811061252557fe5b90506020028101906125379190614702565b89898781811061254357fe5b90506020028101906125559190614702565b6040518563ffffffff1660e01b815260040161257494939291906142b9565b600060405180830381600087803b15801561258e57600080fd5b505af11580156125a2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526125ca9190810190613fb0565b505b50600101612451565b5060006125e0613010565b905060005b82811015612604576125fc84848381811061236d57fe5b6001016125e5565b5050505050505050565b6000610526826001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b15801561264c57600080fd5b505afa158015612660573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126849190613dc6565b6136b1565b600080612695836104ef565b90506126a0816136f9565b9392505050565b60008060006126b461383a565b9050836001600160a01b0316635909c0d56040518163ffffffff1660e01b815260040160206040518083038186803b1580156126ef57600080fd5b505afa158015612703573d6000803e3d6000fd5b505050506040513d602081101561271957600080fd5b505160408051635a3d549360e01b815290519194506001600160a01b03861691635a3d549391600480820192602092909190829003018186803b15801561275f57600080fd5b505afa158015612773573d6000803e3d6000fd5b505050506040513d602081101561278957600080fd5b505160408051630240bc6b60e21b81529051919350600091829182916001600160a01b03891691630902f1ac916004808301926060929190829003018186803b1580156127d557600080fd5b505afa1580156127e9573d6000803e3d6000fd5b505050506040513d60608110156127ff57600080fd5b5080516020820151604090920151909450909250905063ffffffff8082169085161461286c5780840363ffffffff81166128398486612876565b516001600160e01b031602969096019563ffffffff811661285a8585612876565b516001600160e01b0316029590950194505b5050509193909250565b61287e613ca8565b6000826001600160701b0316116128dc576040805162461bcd60e51b815260206004820152601760248201527f4669786564506f696e743a204449565f42595f5a45524f000000000000000000604482015290519081900360640190fd5b6040805160208101909152806001600160701b0384166dffffffffffffffffffffffffffff60701b607087901b168161291157fe5b046001600160e01b0316815250905092915050565b60007fa4690066220620100ea0109a1e46cbd5096ab757e3117d17b6ee1b6f27fe420c821415612958575060006104c6565b7f6ecfd38039ec34885e5db2042e2d32737d0642a40a759e9d1076d51bccec8de9821415612988575060016104c6565b7f00000000000000000000000000000000000000000000000000000000000000008214156129b8575060026104c6565b7f00000000000000000000000000000000000000000000000000000000000000008214156129e8575060036104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612a18575060046104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612a48575060056104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612a78575060066104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612aa8575060076104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612ad8575060086104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612b08575060096104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612b385750600a6104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612b685750600b6104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612b985750600c6104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612bc85750600d6104c6565b7f0000000000000000000000000000000000000000000000000000000000000000821415612bf85750600e6104c6565b50600019919050565b60007f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b0316826001600160a01b03161415612c45575060006104c6565b7f000000000000000000000000cd3b51d98478d53f4515a306be565c6eebef1d586001600160a01b0316826001600160a01b03161415612c87575060016104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612cc9575060026104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612d0b575060036104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612d4d575060046104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612d8f575060056104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612dd1575060066104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612e13575060076104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612e55575060086104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612e97575060096104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612ed95750600a6104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612f1b5750600b6104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612f5d5750600c6104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612f9f5750600d6104c6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415612bf85750600e6104c6565b6000612feb613c5c565b612ff4836105f2565b6020908101516000908152600390915260409020549392505050565b6000806000613020600854610476565b90508060600151600581111561303257fe5b6002148061304f57508060600151600581111561304b57fe5b6003145b156130fc5760078054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526130f593909290918301828280156130e15780601f106130b6576101008083540402835291602001916130e1565b820191906000526020600020905b8154815290600101906020018083116130c457829003601f168201915b505050505082670de0b6b3a7640000613844565b91506131e8565b8060600151600581111561310c57fe5b6005141561311d576130f581613984565b604051633b4bbd1d60e11b81526001600160a01b037f000000000000000000000000a61843f4ea67faa7816b928010c8ca360f76cc9916906376977a3a9061318c907f000000000000000000000000fceadafab14d46e20144f48824d0c09b1a03f2bc9060079060040161418d565b60206040518083038186803b1580156131a457600080fd5b505afa1580156131b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131dc9190614049565b6001600160401b031691505b816132055760405162461bcd60e51b81526004016104bd90614416565b50905090565b6000613216836104ef565b905060028160600151600581111561322a57fe5b1480613245575060038160600151600581111561324357fe5b145b8061325f575060048160600151600581111561325d57fe5b145b80613279575060058160600151600581111561327757fe5b145b6132955760405162461bcd60e51b81526004016104bd906143b9565b60405142906000906132ab9086906020016140e7565b6040516020818303038152906040528051906020012090508060085414156132f2576008805460009081526002602090815260408083208890559254825260039052208290555b60048360600151600581111561330457fe5b141561342a57604051633b4bbd1d60e11b81526000906001600160a01b037f000000000000000000000000a61843f4ea67faa7816b928010c8ca360f76cc9916906376977a3a9061337b907f000000000000000000000000fceadafab14d46e20144f48824d0c09b1a03f2bc908a90600401614169565b60206040518083038186803b15801561339357600080fd5b505afa1580156133a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133cb9190614049565b60008381526002602090815260408083206001600160401b039490941693849055600390915290819020859055519091506000805160206147db8339815191529061341990889084906142fe565b60405180910390a1505050506136ad565b60058360600151600581111561343c57fe5b141561349857600061344d84613984565b6000838152600260209081526040808320849055600390915290819020859055519091506000805160206147db8339815191529061348e90889084906142fe565b60405180910390a1505b60006008548214156134ab5750836134d4565b60008460e001516134bc57856134c3565b8461010001515b90506134d0878683613844565b9150505b6003846060015160058111156134e657fe5b14806134f4575060045460ff165b15613544576000828152600260209081526040808320849055600390915290819020849055516000805160206147db8339815191529061353790889084906142fe565b60405180910390a16136a8565b604051633b4bbd1d60e11b81526000906001600160a01b037f000000000000000000000000a61843f4ea67faa7816b928010c8ca360f76cc9916906376977a3a906135b5907f000000000000000000000000fceadafab14d46e20144f48824d0c09b1a03f2bc908b90600401614169565b60206040518083038186803b1580156135cd57600080fd5b505afa1580156135e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136059190614049565b6001600160401b0316905061361a8183613a40565b1561366a576000838152600260209081526040808320849055600390915290819020859055516000805160206147db8339815191529061365d90899084906142fe565b60405180910390a16136a6565b7f90756d4c8646a4591078abac0e4e32dfa8437921729e36d51b88b659d265bfde87828460405161369d93929190614320565b60405180910390a15b505b505050505b5050565b60006136bb613c5c565b6136c4836105f2565b905080604001516136ea6c0c9f2c9cd04674edea400000006136e5846136f9565b613ac8565b816136f157fe5b049392505050565b600060028260600151600581111561370d57fe5b1480613728575060038260600151600581111561372657fe5b145b80613742575060048260600151600581111561374057fe5b145b8061375c575060058260600151600581111561375a57fe5b145b1561377c57506020808201516000908152600290915260409020546104c6565b60018260600151600581111561378e57fe5b141561379f575060808101516104c6565b6000826060015160058111156137b157fe5b14156104c6576000600260006040516020016137cc90614146565b604051602081830303815290604052805190602001208152602001908152602001600020549050600081116138135760405162461bcd60e51b81526004016104bd906145be565b670de0b6b3a764000061382a828560800151613ac8565b8161383157fe5b049150506104c6565b63ffffffff421690565b60008060008061385386613b02565b9250925092508042116138785760405162461bcd60e51b81526004016104bd90614552565b6000814203905060006040518060200160405280838688038161389757fe5b046001600160e01b0316815250905060006138b182613c0e565b905060006138bf828a613ac8565b90506000670de0b6b3a7640000806138db848e60400151613ac8565b816138e257fe5b04816138ea57fe5b0490506008548c60405160200161390191906140e7565b6040516020818303038152906040528051906020012014156139385760095461392d82620f4240613ac8565b8161393457fe5b0490505b7ff63d078e0de851897107641e96093a59e5ddc3c25e7b85a2585e3eba9e774a7b8c82884260405161396d9493929190614345565b60405180910390a19b9a5050505050505050505050565b600a54815160405163775934ff60e11b81526000926001600160a01b03169163eeb269fe916139b69190600401614155565b60206040518083038186803b1580156139ce57600080fd5b505afa1580156139e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a069190614031565b9050613a1581620f4240613ac8565b9050613a25818360400151613ac8565b90506ec097ce7bc90715b34b9f1000000000815b0492915050565b60008215613abf57600083613a5d84670de0b6b3a7640000613ac8565b81613a6457fe5b0490507f00000000000000000000000000000000000000000000000010a741a4627800008111158015613ab757507f0000000000000000000000000000000000000000000000000b1a2bc2ec5000008110155b915050610526565b50600092915050565b600082613ad757506000610526565b82820282848281613ae457fe5b04146126a05760405162461bcd60e51b81526004016104bd90614457565b600080600080846020015190506000613b1a86613c2a565b60008381526006602090815260409182902082518084019093528054808452600190910154918301919091529192509042037f00000000000000000000000000000000000000000000000000000000000007088110613be9578151600085815260056020908152604080832093845581860180516001958601556006835292819020428082559401879055908b015185519251915190937fe37d39315e3419c0937360f1ac88f2c52ecf67e3b22b367f82047ddb4591904a93613be093909289906146e7565b60405180910390a25b5050600091825260056020526040909120600181015490549196909550909350915050565b80516000906612725dd1d243ab906001600160e01b0316613a39565b6000806000613c3c8460a001516126a7565b50915091508360c0015115613c545791506104c69050565b5090506104c6565b6040805161012081018252600080825260208201819052918101829052906060820190815260006020820181905260408201819052606082018190526080820181905260a09091015290565b60408051602081019091526000815290565b6000613ccd613cc884614769565b614746565b9050828152838383011115613ce157600080fd5b828260208301376000602084830101529392505050565b60008083601f840112613d09578182fd5b5081356001600160401b03811115613d1f578182fd5b6020830191508360208083028501011115613d3957600080fd5b9250929050565b600082601f830112613d50578081fd5b6126a083833560208501613cba565b600082601f830112613d6f578081fd5b8151613d7d613cc882614769565b818152846020838601011115613d91578283fd5b613da2826020830160208701614796565b949350505050565b600060208284031215613dbb578081fd5b81356126a0816147c2565b600060208284031215613dd7578081fd5b81516126a0816147c2565b60008060008060008060608789031215613dfa578182fd5b86356001600160401b0380821115613e10578384fd5b613e1c8a838b01613cf8565b90985096506020890135915080821115613e34578384fd5b613e408a838b01613cf8565b90965094506040890135915080821115613e58578384fd5b50613e6589828a01613cf8565b979a9699509497509295939492505050565b60008060208385031215613e89578182fd5b82356001600160401b03811115613e9e578283fd5b613eaa85828601613cf8565b90969095509350505050565b600060208284031215613ec7578081fd5b5035919050565b600080600060608486031215613ee2578283fd5b8351925060208401519150604084015160ff81168114613f00578182fd5b809150509250925092565b60008060408385031215613f1d578182fd5b82356001600160401b0380821115613f33578384fd5b613f3f86838701613d40565b93506020850135915080821115613f54578283fd5b50613f6185828601613d40565b9150509250929050565b600060208284031215613f7c578081fd5b81356001600160401b03811115613f91578182fd5b8201601f81018413613fa1578182fd5b613da284823560208401613cba565b600060208284031215613fc1578081fd5b81516001600160401b03811115613fd6578182fd5b613da284828501613d5f565b60008060408385031215613ff4578081fd5b82516001600160401b03811115614009578182fd5b61401585828601613d5f565b9250506020830151614026816147c2565b809150509250929050565b600060208284031215614042578081fd5b5051919050565b60006020828403121561405a578081fd5b81516001600160401b03811681146126a0578182fd5b6001600160a01b03169052565b15159052565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600681106140b757fe5b9052565b600081518084526140d3816020860160208601614796565b601f01601f19169290920160200192915050565b600082516140f9818460208701614796565b9190910192915050565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b65726f7461746560d01b815260060190565b6208aa8960eb1b815260030190565b6001600160a01b0391909116815260200190565b6001600160a01b0383168152604060208201819052600090613da2908301846140bb565b60006040820160018060a01b038516835260206040818501528285546001808216600081146141c357600181146141e157614219565b60028304607f16865260ff1983166060890152608088019350614219565b600283048087526141f18a61478a565b885b8281101561420f5781548b8201606001529084019087016141f3565b8a01606001955050505b509198975050505050505050565b6000602080830181845280855180835260408601915060408482028701019250838701855b8281101561427a57603f198886030184526142688583516140bb565b9450928501929085019060010161424c565b5092979650505050505050565b901515815260200190565b90815260200190565b93845260ff9290921660208401526040830152606082015260800190565b6000604082526142cd604083018688614083565b82810360208401526142e0818587614083565b979650505050505050565b6000602082526126a060208301846140bb565b60006040825261431160408301856140bb565b90508260208301529392505050565b60006060825261433360608301866140bb565b60208301949094525060400152919050565b60006080825261435860808301876140bb565b6020830195909552506040810192909252606090910152919050565b60208082526025908201527f746f6b656e20636f6e6669672062792073796d626f6c2068617368206e6f7420604082015264199bdd5b9960da1b606082015260800190565b6020808252603f908201527f6f6e6c79207265706f727465722c20756e69737761702c206f7261636c65206f60408201527f72207369676e65642d6f6e6c79207072696365732067657420706f7374656400606082015260800190565b60208082526021908201527f5265666572656e636520617373657420707269636520756e617661696c61626c6040820152606560f81b606082015260800190565b60208082526017908201527f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000604082015260600190565b6020808252601690820152751d1bdad95b8818dbdb999a59c81b9bdd08199bdd5b9960521b604082015260600190565b60208082526030908201527f696e76616c69646174696f6e206d657373616765206d75737420636f6d65206660408201526f3937b6903a3432903932b837b93a32b960811b606082015260800190565b60208082526024908201527f746f6b656e20636f6e66696720627920756e6465726c79696e67206e6f7420666040820152631bdd5b9960e21b606082015260800190565b6020808252601a908201527f6e6f77206d75737420636f6d65206166746572206265666f7265000000000000604082015260600190565b6020808252818101527f696e76616c6964206d657373616765206d7573742062652027726f7461746527604082015260600190565b6020808252602c908201527f455448207072696365206e6f74207365742c2063616e6e6f7420636f6e76657260408201526b7420746f20646f6c6c61727360a01b606082015260800190565b60208082526023908201527f6d6573736167657320616e64207369676e617475726573206d75737420626520604082015262313a3160e81b606082015260800190565b81516001600160a01b031681526020808301519082015260408083015190820152606080830151610120830191614686908401826140ad565b506080830151608083015260a08301516146a360a0840182614070565b5060c08301516146b660c084018261407d565b5060e08301516146c960e084018261407d565b5061010092830151919092015290565b918252602082015260400190565b93845260208401929092526040830152606082015260800190565b6000808335601e19843603018112614718578283fd5b8301803591506001600160401b03821115614731578283fd5b602001915036819003821315613d3957600080fd5b6040518181016001600160401b038111828210171561476157fe5b604052919050565b60006001600160401b0382111561477c57fe5b50601f01601f191660200190565b60009081526020902090565b60005b838110156147b1578181015183820152602001614799565b838111156123c35750506000910152565b6001600160a01b03811681146147d757600080fd5b5056fe159e83f4712ba2552e68be9d848e49bf6dd35c24f19564ffd523b6549450a2f4a2646970667358221220657fd85446136f43dc5c1d46d16afc2b709f7aeec99f525410e6ac78a38f41df64736f6c63430007060033

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

000000000000000000000000a61843f4ea67faa7816b928010c8ca360f76cc99000000000000000000000000fceadafab14d46e20144f48824d0c09b1a03f2bc000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000000000000000000002c68af0bb14000000000000000000000000000000000000000000000000000000000000000007080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000003c00000000000000000000000000000000000000000000000000000000000000004474c4d52000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeea4690066220620100ea0109a1e46cbd5096ab757e3117d17b6ee1b6f27fe420c0000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b929914b89584b4081c7966ac6287636f7efd053000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd3b51d98478d53f4515a306be565c6eebef1d586ecfd38039ec34885e5db2042e2d32737d0642a40a759e9d1076d51bccec8de90000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000099588867e817023162f4d4829995299054a5fc570000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : priceData_ (address): 0xA61843f4eA67faA7816b928010C8cA360F76cC99
Arg [1] : reporter_ (address): 0xfCEAdAFab14d46e20144F48824d0C09B1a03F2BC
Arg [2] : referenceAssetSymbol_ (string): GLMR
Arg [3] : usdBaseUnit_ (uint256): 1000000
Arg [4] : anchorToleranceMantissa_ (uint256): 200000000000000000
Arg [5] : anchorPeriod_ (uint256): 1800
Arg [6] : registry_ (address): 0x0000000000000000000000000000000000000000
Arg [7] : configs (tuple[]): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]

-----Encoded View---------------
31 Constructor Arguments found :
Arg [0] : 000000000000000000000000a61843f4ea67faa7816b928010c8ca360f76cc99
Arg [1] : 000000000000000000000000fceadafab14d46e20144f48824d0c09b1a03f2bc
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [3] : 00000000000000000000000000000000000000000000000000000000000f4240
Arg [4] : 00000000000000000000000000000000000000000000000002c68af0bb140000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000708
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [8] : 00000000000000000000000000000000000000000000000000000000000003c0
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [10] : 474c4d5200000000000000000000000000000000000000000000000000000000
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [12] : 000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
Arg [13] : a4690066220620100ea0109a1e46cbd5096ab757e3117d17b6ee1b6f27fe420c
Arg [14] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Arg [15] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [16] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [17] : 000000000000000000000000b929914b89584b4081c7966ac6287636f7efd053
Arg [18] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [19] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [20] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [21] : 000000000000000000000000cd3b51d98478d53f4515a306be565c6eebef1d58
Arg [22] : 6ecfd38039ec34885e5db2042e2d32737d0642a40a759e9d1076d51bccec8de9
Arg [23] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Arg [24] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [25] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [26] : 00000000000000000000000099588867e817023162f4d4829995299054a5fc57
Arg [27] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [28] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [29] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [30] : 0000000000000000000000000000000000000000000000000000000000000000


Block Transaction Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Txn Hash Block Value Eth2 PubKey Valid
View All Deposits
[ 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.