Contract 0xe0E828643266Fab54716503f82FB404867214f39 2

 

Contract Overview

Balance:
0 MATIC

MATIC Value:
$0.00

Token:
 
Txn Hash
Method
Block
From
To
Value [Txn Fee]
0xac60623eca12390b19b86d474e5c37bed65ceb46512a514b02dfa67fb2594e81Update Price226344932021-12-17 14:27:48526 days 9 hrs ago0x236eccab8cdcfedb099de85c4060024ba3ce4d46 IN  0xe0e828643266fab54716503f82fb404867214f390 MATIC0.0012222330
0x51d210cc1074c2584c4f99d1298e2a2a323fdca271ca7f48aed5d41f58015b92Update Price226344612021-12-17 14:26:44526 days 9 hrs ago0x236eccab8cdcfedb099de85c4060024ba3ce4d46 IN  0xe0e828643266fab54716503f82fb404867214f390 MATIC0.003159630
0x79da7d019238e9e362a75ee16a5e22cdd378f44d82150c0299874f837da55b560x60c06040226343212021-12-17 14:21:56526 days 9 hrs ago0x236eccab8cdcfedb099de85c4060024ba3ce4d46 IN  Create: IndexedUniswapV2Oracle0 MATIC0.0823346730
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
IndexedUniswapV2Oracle

Compiler Version
v0.6.8+commit.0bbfe453

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, GNU GPLv3 license
File 1 of 10 : IndexedUniswapV2Oracle.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

/* ==========  Internal Libraries  ========== */
import "./lib/PriceLibrary.sol";
import "./lib/FixedPoint.sol";
import "./lib/IndexedPriceMapLibrary.sol";

/* ==========  Internal Inheritance  ========== */
import "./interfaces/IIndexedUniswapV2Oracle.sol";


contract IndexedUniswapV2Oracle is IIndexedUniswapV2Oracle {
  using PriceLibrary for address;
  using PriceLibrary for PriceLibrary.PriceObservation;
  using PriceLibrary for PriceLibrary.TwoWayAveragePrice;
  using FixedPoint for FixedPoint.uq112x112;
  using FixedPoint for FixedPoint.uq144x112;
  using IndexedPriceMapLibrary for IndexedPriceMapLibrary.IndexedPriceMap;


/* ==========  Immutables  ========== */

  address internal immutable _uniswapFactory;
  address internal immutable _weth;

/* ==========  Storage  ========== */

  // Price observations for tokens indexed by hour.
  mapping(address => IndexedPriceMapLibrary.IndexedPriceMap) internal _tokenPriceMaps;

/* ==========  Modifiers  ========== */

  modifier validMinMax(uint256 minTimeElapsed, uint256 maxTimeElapsed) {
    require(
      maxTimeElapsed >= minTimeElapsed,
      "IndexedUniswapV2Oracle::validMinMax: Minimum age can not be higher than maximum."
    );
    _;
  }

/* ==========  Constructor  ========== */

  constructor(address uniswapFactory, address weth) public {
    _uniswapFactory = uniswapFactory;
    _weth = weth;
  }

/* ==========  Mutative Functions  ========== */

  /**
   * @dev Attempts to update the price of `token` and returns a boolean
   * indicating whether it was updated.
   *
   * Note: The price can be updated if there is no observation for the current hour
   * and at least 30 minutes have passed since the last observation.
   */
  function updatePrice(address token) public override returns (bool/* didUpdatePrice */) {
    if (token == _weth) return true;
    PriceLibrary.PriceObservation memory observation = _uniswapFactory.observeTwoWayPrice(token, _weth);
    return _tokenPriceMaps[token].writePriceObservation(observation);
  }

  /**
   * @dev Attempts to update the price of each token in `tokens` and returns a boolean
   * array indicating which tokens had their prices updated.
   *
   * Note: The price can be updated if there is no observation for the current hour
   * and at least 30 minutes have passed since the last observation.
   */
  function updatePrices(address[] calldata tokens)
    external
    override
    returns (bool[] memory pricesUpdated)
  {
    uint256 len = tokens.length;
    pricesUpdated = new bool[](len);
    for (uint256 i = 0; i < len; i++) {
      pricesUpdated[i] = updatePrice(tokens[i]);
    }
  }

/* ==========  Meta Price Queries  ========== */

  /**
   * @dev Returns a boolean indicating whether a price was recorded for `token` at `priceKey`.
   *
   * @param token Token to check if the oracle has a price for
   * @param priceKey Index of the hour to check
   */
  function hasPriceObservationInWindow(address token, uint256 priceKey)
    external view override returns (bool)
  {
    return _tokenPriceMaps[token].hasPriceInWindow(priceKey);
  }


  /**
   * @dev Returns the price observation for `token` recorded in `priceKey`.
   * Reverts if no prices have been recorded for that key.
   *
   * @param token Token to retrieve a price for
   * @param priceKey Index of the hour to query
   */
  function getPriceObservationInWindow(address token, uint256 priceKey)
    external
    view
    override
    returns (PriceLibrary.PriceObservation memory observation)
  {
    observation = _tokenPriceMaps[token].getPriceInWindow(priceKey);
    require(
      observation.timestamp != 0,
      "IndexedUniswapV2Oracle::getPriceObservationInWindow: No price observed in given hour."
    );
  }

  /**
   * @dev Returns all price observations for `token` recorded between `timeFrom` and `timeTo`.
   */
  function getPriceObservationsInRange(address token, uint256 timeFrom, uint256 timeTo)
    external
    view
    override
    returns (PriceLibrary.PriceObservation[] memory prices)
  {
    prices = _tokenPriceMaps[token].getPriceObservationsInRange(timeFrom, timeTo);
  }

/* ==========  Price Update Queries  ========== */

  /**
   * @dev Returns a boolean indicating whether the price of `token` can be updated.
   *
   * Note: The price can be updated if there is no observation for the current hour
   * and at least 30 minutes have passed since the last observation.
   */
  function canUpdatePrice(address token) external view override returns (bool/* canUpdatePrice */) {
    if (!_uniswapFactory.pairInitialized(token, _weth)) return false;
    return _tokenPriceMaps[token].canUpdatePrice(uint32(now));
  }

  /**
   * @dev Returns a boolean array indicating whether the price of each token in
   * `tokens` can be updated.
   *
   * Note: The price can be updated if there is no observation for the current hour
   * and at least 30 minutes have passed since the last observation.
   */
  function canUpdatePrices(address[] calldata tokens) external view override returns (bool[] memory canUpdateArr) {
    uint256 len = tokens.length;
    canUpdateArr = new bool[](len);
    for (uint256 i = 0; i < len; i++) {
      address token = tokens[i];
      bool timeAllowed = _tokenPriceMaps[token].canUpdatePrice(uint32(now));
      canUpdateArr[i] = timeAllowed && _uniswapFactory.pairInitialized(token, _weth);
    }
  }

/* ==========  Price Queries: Singular  ========== */

  /**
   * @dev Returns the TwoWayAveragePrice struct representing the average price of
   * weth in terms of `token` and the average price of `token` in terms of weth.
   *
   * Computes the time-weighted average price of weth in terms of `token` and the price
   * of `token` in terms of weth by getting the current prices from Uniswap and searching
   * for a historical price which is between `minTimeElapsed` and `maxTimeElapsed` seconds old.
   *
   * Note: `maxTimeElapsed` is only accurate to the nearest hour (rounded down) unless
   * it is less than one hour.
   * Note: `minTimeElapsed` is only accurate to the nearest hour (rounded up) unless
   * it is less than one hour.
   */
  function computeTwoWayAveragePrice(
    address token,
    uint256 minTimeElapsed,
    uint256 maxTimeElapsed
  )
    external
    view
    override
    validMinMax(minTimeElapsed, maxTimeElapsed)
    returns (PriceLibrary.TwoWayAveragePrice memory)
  {
    return _getTwoWayPrice(token, minTimeElapsed, maxTimeElapsed);
  }

  /**
   * @dev Returns the UQ112x112 struct representing the average price of
   * `token` in terms of weth.
   *
   * Computes the time-weighted average price of `token` in terms of weth by getting the
   * current price from Uniswap and searching for a historical price which is between
   * `minTimeElapsed` and `maxTimeElapsed` seconds old.
   *
   * Note: `maxTimeElapsed` is only accurate to the nearest hour (rounded down) unless
   * it is less than one hour.
   * Note: `minTimeElapsed` is only accurate to the nearest hour (rounded up) unless
   * it is less than one hour.
   */
  function computeAverageTokenPrice(
    address token,
    uint256 minTimeElapsed,
    uint256 maxTimeElapsed
  )
    external
    view
    override
    validMinMax(minTimeElapsed, maxTimeElapsed)
    returns (FixedPoint.uq112x112 memory priceAverage)
  {
    return _getTokenPrice(token, minTimeElapsed, maxTimeElapsed);
  }

  /**
   * @dev Returns the UQ112x112 struct representing the average price of
   * weth in terms of `token`.
   *
   * Computes the time-weighted average price of weth in terms of `token` by getting the
   * current price from Uniswap and searching for a historical price which is between
   * `minTimeElapsed` and `maxTimeElapsed` seconds old.
   *
   * Note: `maxTimeElapsed` is only accurate to the nearest hour (rounded down) unless
   * it is less than one hour.
   * Note: `minTimeElapsed` is only accurate to the nearest hour (rounded up) unless
   * it is less than one hour.
   */
  function computeAverageEthPrice(
    address token,
    uint256 minTimeElapsed,
    uint256 maxTimeElapsed
  )
    external
    view
    override
    validMinMax(minTimeElapsed, maxTimeElapsed)
    returns (FixedPoint.uq112x112 memory priceAverage)
  {
    return _getEthPrice(token, minTimeElapsed, maxTimeElapsed);
  }

/* ==========  Price Queries: Multiple  ========== */

  /**
   * @dev Returns the TwoWayAveragePrice structs representing the average price of
   * weth in terms of each token in `tokens` and the average price of each token
   * in terms of weth.
   *
   * Computes the time-weighted average price of weth in terms of each token and the price
   * of each token in terms of weth by getting the current prices from Uniswap and searching
   * for a historical price which is between `minTimeElapsed` and `maxTimeElapsed` seconds old.
   *
   * Note: `maxTimeElapsed` is only accurate to the nearest hour (rounded down) unless
   * it is less than one hour.
   * Note: `minTimeElapsed` is only accurate to the nearest hour (rounded up) unless
   * it is less than one hour.
   */
  function computeTwoWayAveragePrices(
    address[] calldata tokens,
    uint256 minTimeElapsed,
    uint256 maxTimeElapsed
  )
    external
    view
    override
    validMinMax(minTimeElapsed, maxTimeElapsed)
    returns (PriceLibrary.TwoWayAveragePrice[] memory prices)
  {
    uint256 len = tokens.length;
    prices = new PriceLibrary.TwoWayAveragePrice[](len);
    for (uint256 i = 0; i < len; i++) {
      prices[i] = _getTwoWayPrice(tokens[i], minTimeElapsed, maxTimeElapsed);
    }
  }

  /**
   * @dev Returns the UQ112x112 structs representing the average price of
   * each token in `tokens` in terms of weth.
   *
   * Computes the time-weighted average price of each token in terms of weth by getting
   * the current price from Uniswap and searching for a historical price which is between
   * `minTimeElapsed` and `maxTimeElapsed` seconds old.
   *
   * Note: `maxTimeElapsed` is only accurate to the nearest hour (rounded down) unless
   * it is less than one hour.
   * Note: `minTimeElapsed` is only accurate to the nearest hour (rounded up) unless
   * it is less than one hour.
   */
  function computeAverageTokenPrices(
    address[] calldata tokens,
    uint256 minTimeElapsed,
    uint256 maxTimeElapsed
  )
    external
    view
    override
    validMinMax(minTimeElapsed, maxTimeElapsed)
    returns (FixedPoint.uq112x112[] memory averagePrices)
  {
    uint256 len = tokens.length;
    averagePrices = new FixedPoint.uq112x112[](len);
    for (uint256 i = 0; i < len; i++) {
      averagePrices[i] = _getTokenPrice(tokens[i], minTimeElapsed, maxTimeElapsed);
    }
  }

  /**
   * @dev Returns the UQ112x112 structs representing the average price of
   * weth in terms of each token in `tokens`.
   *
   * Computes the time-weighted average price of weth in terms of each token by getting
   * the current price from Uniswap and searching for a historical price which is between
   * `minTimeElapsed` and `maxTimeElapsed` seconds old.
   *
   * Note: `maxTimeElapsed` is only accurate to the nearest hour (rounded down) unless
   * it is less than one hour.
   * Note: `minTimeElapsed` is only accurate to the nearest hour (rounded up) unless
   * it is less than one hour.
   */
  function computeAverageEthPrices(
    address[] calldata tokens,
    uint256 minTimeElapsed,
    uint256 maxTimeElapsed
  )
    external
    view
    override
    validMinMax(minTimeElapsed, maxTimeElapsed)
    returns (FixedPoint.uq112x112[] memory averagePrices)
  {
    uint256 len = tokens.length;
    averagePrices = new FixedPoint.uq112x112[](len);
    for (uint256 i = 0; i < len; i++) {
      averagePrices[i] = _getEthPrice(tokens[i], minTimeElapsed, maxTimeElapsed);
    }
  }

/* ==========  Value Queries: Singular  ========== */

  /**
   * @dev Compute the average value of `tokenAmount` ether in terms of weth.
   *
   * Computes the time-weighted average price of `token` in terms of weth by getting
   * the current price from Uniswap and searching for a historical price which is between
   * `minTimeElapsed` and `maxTimeElapsed` seconds old, then multiplies by `wethAmount`.
   *
   * Note: `maxTimeElapsed` is only accurate to the nearest hour (rounded down) unless
   * it is less than one hour.
   * Note: `minTimeElapsed` is only accurate to the nearest hour (rounded up) unless
   * it is less than one hour.
   */
  function computeAverageEthForTokens(
    address token,
    uint256 tokenAmount,
    uint256 minTimeElapsed,
    uint256 maxTimeElapsed
  )
    external
    view
    override
    validMinMax(minTimeElapsed, maxTimeElapsed)
    returns (uint144 /* averageValueInWETH */)
  {
    FixedPoint.uq112x112 memory tokenPrice = _getTokenPrice(token, minTimeElapsed, maxTimeElapsed);
    return tokenPrice.mul(tokenAmount).decode144();
  }

  /**
   * @dev Compute the average value of `wethAmount` ether in terms of `token`.
   *
   * Computes the time-weighted average price of weth in terms of the token by getting
   * the current price from Uniswap and searching for a historical price which is between
   * `minTimeElapsed` and `maxTimeElapsed` seconds old, then multiplies by `wethAmount`.
   *
   * Note: `maxTimeElapsed` is only accurate to the nearest hour (rounded down) unless
   * it is less than one hour.
   * Note: `minTimeElapsed` is only accurate to the nearest hour (rounded up) unless
   * it is less than one hour.
   */
  function computeAverageTokensForEth(
    address token,
    uint256 wethAmount,
    uint256 minTimeElapsed,
    uint256 maxTimeElapsed
  )
    external
    view
    override
    validMinMax(minTimeElapsed, maxTimeElapsed)
    returns (uint144 /* averageValueInToken */)
  {
    FixedPoint.uq112x112 memory ethPrice = _getEthPrice(token, minTimeElapsed, maxTimeElapsed);
    return ethPrice.mul(wethAmount).decode144();
  }

/* ==========  Value Queries: Multiple  ========== */

  /**
   * @dev Compute the average value of each amount of tokens in `tokenAmounts` in terms
   * of the corresponding token in `tokens`.
   *
   * Computes the time-weighted average price of each token in terms of weth by getting
   * the current price from Uniswap and searching for a historical price which is between
   * `minTimeElapsed` and `maxTimeElapsed` seconds old, then multiplies by the corresponding
   * amount in `tokenAmounts`.
   *
   * Note: `maxTimeElapsed` is only accurate to the nearest hour (rounded down) unless
   * it is less than one hour.
   * Note: `minTimeElapsed` is only accurate to the nearest hour (rounded up) unless
   * it is less than one hour.
   */
  function computeAverageEthForTokens(
    address[] calldata tokens,
    uint256[] calldata tokenAmounts,
    uint256 minTimeElapsed,
    uint256 maxTimeElapsed
  )
    external
    view
    override
    validMinMax(minTimeElapsed, maxTimeElapsed)
    returns (uint144[] memory averageValuesInWETH)
  {
    uint256 len = tokens.length;
    require(
      tokenAmounts.length == len,
      "IndexedUniswapV2Oracle::computeAverageEthForTokens: Tokens and amounts have different lengths."
    );
    averageValuesInWETH = new uint144[](len);
    for (uint256 i = 0; i < len; i++) {
      averageValuesInWETH[i] = _getTokenPrice(
        tokens[i],
        minTimeElapsed,
        maxTimeElapsed
      ).mul(tokenAmounts[i]).decode144();
    }
  }

  /**
   * @dev Compute the average value of each amount of ether in `wethAmounts` in terms
   * of the corresponding token in `tokens`.
   *
   * Computes the time-weighted average price of weth in terms of each token by getting
   * the current price from Uniswap and searching for a historical price which is between
   * `minTimeElapsed` and `maxTimeElapsed` seconds old, then multiplies by the corresponding
   * amount in `wethAmounts`.
   *
   * Note: `maxTimeElapsed` is only accurate to the nearest hour (rounded down) unless
   * it is less than one hour.
   * Note: `minTimeElapsed` is only accurate to the nearest hour (rounded up) unless
   * it is less than one hour.
   */
  function computeAverageTokensForEth(
    address[] calldata tokens,
    uint256[] calldata wethAmounts,
    uint256 minTimeElapsed,
    uint256 maxTimeElapsed
  )
    external
    view
    override
    validMinMax(minTimeElapsed, maxTimeElapsed)
    returns (uint144[] memory averageValuesInWETH)
  {
    uint256 len = tokens.length;
    require(
      wethAmounts.length == len,
      "IndexedUniswapV2Oracle::computeAverageTokensForEth: Tokens and amounts have different lengths."
    );
    averageValuesInWETH = new uint144[](len);
    for (uint256 i = 0; i < len; i++) {
      averageValuesInWETH[i] = _getEthPrice(
        tokens[i],
        minTimeElapsed,
        maxTimeElapsed
      ).mul(wethAmounts[i]).decode144();
    }
  }

/* ==========  Internal Functions  ========== */
  function _getTwoWayPrice(
    address token,
    uint256 minTimeElapsed,
    uint256 maxTimeElapsed
  )
    internal
    view
    returns (PriceLibrary.TwoWayAveragePrice memory)
  {
    if (token == _weth) {
      return PriceLibrary.TwoWayAveragePrice(
        FixedPoint.encode(1)._x,
        FixedPoint.encode(1)._x
      );
    }
    // Get the current cumulative price
    PriceLibrary.PriceObservation memory current = _uniswapFactory.observeTwoWayPrice(token, _weth);
    // Get the latest usable price
    (bool foundPrice, uint256 lastPriceKey) = _tokenPriceMaps[token].getLastPriceObservation(
      current.timestamp,
      minTimeElapsed,
      maxTimeElapsed
    );
    require(foundPrice, "IndexedUniswapV2Oracle::_getTwoWayPrice: No price found in provided range.");
    PriceLibrary.PriceObservation memory previous = _tokenPriceMaps[token].priceMap[lastPriceKey];
    return previous.computeTwoWayAveragePrice(current);
  }

  function _getTokenPrice(
    address token,
    uint256 minTimeElapsed,
    uint256 maxTimeElapsed
  )
    internal
    view
    returns (FixedPoint.uq112x112 memory)
  {
    if (token == _weth) {
      return FixedPoint.fraction(1, 1);
    }
    (uint32 timestamp, uint224 priceCumulativeEnd) = _uniswapFactory.observePrice(token, _weth);
    (bool foundPrice, uint256 lastPriceKey) = _tokenPriceMaps[token].getLastPriceObservation(
      timestamp,
      minTimeElapsed,
      maxTimeElapsed
    );
    require(foundPrice, "IndexedUniswapV2Oracle::_getTokenPrice: No price found in provided range.");
    PriceLibrary.PriceObservation storage previous = _tokenPriceMaps[token].priceMap[lastPriceKey];
    return PriceLibrary.computeAveragePrice(
      previous.timestamp,
      previous.priceCumulativeLast,
      timestamp,
      priceCumulativeEnd
    );
  }

  function _getEthPrice(
    address token,
    uint256 minTimeElapsed,
    uint256 maxTimeElapsed
  )
    internal
    view
    returns (FixedPoint.uq112x112 memory)
  {
    if (token == _weth) {
      return FixedPoint.fraction(1, 1);
    }
    (uint32 timestamp, uint224 priceCumulativeEnd) = _uniswapFactory.observePrice(_weth, token);
    (bool foundPrice, uint256 lastPriceKey) = _tokenPriceMaps[token].getLastPriceObservation(
      timestamp,
      minTimeElapsed,
      maxTimeElapsed
    );
    require(foundPrice, "IndexedUniswapV2Oracle::_getEthPrice: No price found in provided range.");
    PriceLibrary.PriceObservation storage previous = _tokenPriceMaps[token].priceMap[lastPriceKey];
    return PriceLibrary.computeAveragePrice(
      previous.timestamp,
      previous.ethPriceCumulativeLast,
      timestamp,
      priceCumulativeEnd
    );
  }
}

File 2 of 10 : PriceLibrary.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

/* ==========  Internal Libraries  ========== */
import "./FixedPoint.sol";
import "./UniswapV2OracleLibrary.sol";
import "./UniswapV2Library.sol";


library PriceLibrary {
  using FixedPoint for FixedPoint.uq112x112;
  using FixedPoint for FixedPoint.uq144x112;

/* ========= Structs ========= */

  struct PriceObservation {
    uint32 timestamp;
    uint224 priceCumulativeLast;
    uint224 ethPriceCumulativeLast;
  }

  /**
   * @dev Average prices for a token in terms of weth and weth in terms of the token.
   *
   * Note: The average weth price is not equivalent to the reciprocal of the average
   * token price. See the UniSwap whitepaper for more info.
   */
  struct TwoWayAveragePrice {
    uint224 priceAverage;
    uint224 ethPriceAverage;
  }

/* ========= View Functions ========= */

  function pairInitialized(
    address uniswapFactory,
    address token,
    address weth
  )
    internal
    view
    returns (bool)
  {
    address pair = UniswapV2Library.pairFor(uniswapFactory, token, weth);
    (uint112 reserve0, uint112 reserve1,) = IUniswapV2Pair(pair).getReserves();
    return reserve0 != 0 && reserve1 != 0;
  }

  function observePrice(
    address uniswapFactory,
    address tokenIn,
    address quoteToken
  )
    internal
    view
    returns (uint32 /* timestamp */, uint224 /* priceCumulativeLast */)
  {
    (address token0, address token1) = UniswapV2Library.sortTokens(tokenIn, quoteToken);
    address pair = UniswapV2Library.calculatePair(uniswapFactory, token0, token1);
    if (token0 == tokenIn) {
      (uint256 price0Cumulative, uint32 blockTimestamp) = UniswapV2OracleLibrary.currentCumulativePrice0(pair);
      return (blockTimestamp, uint224(price0Cumulative));
    } else {
      (uint256 price1Cumulative, uint32 blockTimestamp) = UniswapV2OracleLibrary.currentCumulativePrice1(pair);
      return (blockTimestamp, uint224(price1Cumulative));
    }
  }

  /**
   * @dev Query the current cumulative price of a token in terms of weth
   * and the current cumulative price of weth in terms of the token.
   */
  function observeTwoWayPrice(
    address uniswapFactory,
    address token,
    address weth
  ) internal view returns (PriceObservation memory) {
    (address token0, address token1) = UniswapV2Library.sortTokens(token, weth);
    address pair = UniswapV2Library.calculatePair(uniswapFactory, token0, token1);
    // Get the sorted token prices
    (
      uint256 price0Cumulative,
      uint256 price1Cumulative,
      uint32 blockTimestamp
    ) = UniswapV2OracleLibrary.currentCumulativePrices(pair);
    // Check which token is weth and which is the token,
    // then build the price observation.
    if (token0 == token) {
      return PriceObservation({
        timestamp: blockTimestamp,
        priceCumulativeLast: uint224(price0Cumulative),
        ethPriceCumulativeLast: uint224(price1Cumulative)
      });
    } else {
      return PriceObservation({
        timestamp: blockTimestamp,
        priceCumulativeLast: uint224(price1Cumulative),
        ethPriceCumulativeLast: uint224(price0Cumulative)
      });
    }
  }

/* ========= Utility Functions ========= */

  /**
   * @dev Computes the average price of a token in terms of weth
   * and the average price of weth in terms of a token using two
   * price observations.
   */
  function computeTwoWayAveragePrice(
    PriceObservation memory observation1,
    PriceObservation memory observation2
  ) internal pure returns (TwoWayAveragePrice memory) {
    uint32 timeElapsed = uint32(observation2.timestamp - observation1.timestamp);
    FixedPoint.uq112x112 memory priceAverage = UniswapV2OracleLibrary.computeAveragePrice(
      observation1.priceCumulativeLast,
      observation2.priceCumulativeLast,
      timeElapsed
    );
    FixedPoint.uq112x112 memory ethPriceAverage = UniswapV2OracleLibrary.computeAveragePrice(
      observation1.ethPriceCumulativeLast,
      observation2.ethPriceCumulativeLast,
      timeElapsed
    );
    return TwoWayAveragePrice({
      priceAverage: priceAverage._x,
      ethPriceAverage: ethPriceAverage._x
    });
  }

  function computeAveragePrice(
    uint32 timestampStart,
    uint224 priceCumulativeStart,
    uint32 timestampEnd,
    uint224 priceCumulativeEnd
  ) internal pure returns (FixedPoint.uq112x112 memory) {
    return UniswapV2OracleLibrary.computeAveragePrice(
      priceCumulativeStart,
      priceCumulativeEnd,
      uint32(timestampEnd - timestampStart)
    );
  }

  /**
   * @dev Computes the average price of the token the price observations
   * are for in terms of weth.
   */
  function computeAverageTokenPrice(
    PriceObservation memory observation1,
    PriceObservation memory observation2
  ) internal pure returns (FixedPoint.uq112x112 memory) {
    return UniswapV2OracleLibrary.computeAveragePrice(
      observation1.priceCumulativeLast,
      observation2.priceCumulativeLast,
      uint32(observation2.timestamp - observation1.timestamp)
    );
  }

  /**
   * @dev Computes the average price of weth in terms of the token
   * the price observations are for.
   */
  function computeAverageEthPrice(
    PriceObservation memory observation1,
    PriceObservation memory observation2
  ) internal pure returns (FixedPoint.uq112x112 memory) {
    return UniswapV2OracleLibrary.computeAveragePrice(
      observation1.ethPriceCumulativeLast,
      observation2.ethPriceCumulativeLast,
      uint32(observation2.timestamp - observation1.timestamp)
    );
  }

  /**
   * @dev Compute the average value in weth of `tokenAmount` of the
   * token that the average price values are for.
   */
  function computeAverageEthForTokens(
    TwoWayAveragePrice memory prices,
    uint256 tokenAmount
  ) internal pure returns (uint144) {
    return FixedPoint.uq112x112(prices.priceAverage).mul(tokenAmount).decode144();
  }

  /**
   * @dev Compute the average value of `wethAmount` weth in terms of
   * the token that the average price values are for.
   */
  function computeAverageTokensForEth(
    TwoWayAveragePrice memory prices,
    uint256 wethAmount
  ) internal pure returns (uint144) {
    return FixedPoint.uq112x112(prices.ethPriceAverage).mul(wethAmount).decode144();
  }
}

File 3 of 10 : FixedPoint.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.6.0;


/************************************************************************************************
From https://github.com/Uniswap/uniswap-lib/blob/master/contracts/libraries/FixedPoint.sol

Copied from the github repository at commit hash 9642a0705fdaf36b477354a4167a8cd765250860.

Modifications:
- Removed `sqrt` function

Subject to the GPL-3.0 license
*************************************************************************************************/


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

  // range: [0, 2**144 - 1]
  // resolution: 1 / 2**112
  struct uq144x112 {
    uint _x;
  }

  uint8 private constant RESOLUTION = 112;
  uint private constant Q112 = uint(1) << RESOLUTION;
  uint private constant Q224 = Q112 << RESOLUTION;

  // encode a uint112 as a UQ112x112
  function encode(uint112 x) internal pure returns (uq112x112 memory) {
    return uq112x112(uint224(x) << RESOLUTION);
  }

  // encodes a uint144 as a UQ144x112
  function encode144(uint144 x) internal pure returns (uq144x112 memory) {
    return uq144x112(uint256(x) << RESOLUTION);
  }

  // divide a UQ112x112 by a uint112, returning a UQ112x112
  function div(uq112x112 memory self, uint112 x) internal pure returns (uq112x112 memory) {
    require(x != 0, "FixedPoint: DIV_BY_ZERO");
    return uq112x112(self._x / uint224(x));
  }

  // multiply a UQ112x112 by a uint, returning a UQ144x112
  // reverts on overflow
  function mul(uq112x112 memory self, uint y) internal pure returns (uq144x112 memory) {
    uint z;
    require(
      y == 0 || (z = uint(self._x) * y) / y == uint(self._x),
      "FixedPoint: MULTIPLICATION_OVERFLOW"
    );
    return uq144x112(z);
  }

  // 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) << RESOLUTION) / denominator);
  }

  // decode a UQ112x112 into a uint112 by truncating after the radix point
  function decode(uq112x112 memory self) internal pure returns (uint112) {
    return uint112(self._x >> RESOLUTION);
  }

  // decode a UQ144x112 into a uint144 by truncating after the radix point
  function decode144(uq144x112 memory self) internal pure returns (uint144) {
    return uint144(self._x >> RESOLUTION);
  }

  // take the reciprocal of a UQ112x112
  function reciprocal(uq112x112 memory self) internal pure returns (uq112x112 memory) {
    require(self._x != 0, "FixedPoint: ZERO_RECIPROCAL");
    return uq112x112(uint224(Q224 / self._x));
  }
}

File 4 of 10 : UniswapV2OracleLibrary.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.6.0;

/* ==========  Internal Interfaces  ========== */
import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol";

/* ==========  Internal Libraries  ========== */
import "./FixedPoint.sol";


/************************************************************************************************
Originally from https://github.com/Uniswap/uniswap-v2-periphery/blob/master/contracts/libraries/UniswapV2OracleLibrary.sol

This source code has been modified from the original, which was copied from the github repository
at commit hash 6d03bede0a97c72323fa1c379ed3fdf7231d0b26.

Subject to the GPL-3.0 license
*************************************************************************************************/


// 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 prices using counterfactuals to save gas and avoid a call to sync.
  function currentCumulativePrices(address pair)
    internal
    view
    returns (
      uint256 price0Cumulative,
      uint256 price1Cumulative,
      uint32 blockTimestamp
    )
  {
    blockTimestamp = currentBlockTimestamp();
    price0Cumulative = IUniswapV2Pair(pair).price0CumulativeLast();
    price1Cumulative = IUniswapV2Pair(pair).price1CumulativeLast();

    // if time has elapsed since the last update on the pair, mock the accumulated price values
    (
      uint112 reserve0,
      uint112 reserve1,
      uint32 blockTimestampLast
    ) = IUniswapV2Pair(pair).getReserves();
    require(
      reserve0 != 0 && reserve1 != 0,
      "UniswapV2OracleLibrary::currentCumulativePrices: Pair has no reserves."
    );
    if (blockTimestampLast != blockTimestamp) {
      // subtraction overflow is desired
      uint32 timeElapsed = blockTimestamp - blockTimestampLast;
      // addition overflow is desired
      // counterfactual
      price0Cumulative += (
        uint256(FixedPoint.fraction(reserve1, reserve0)._x) *
        timeElapsed
      );
      // counterfactual
      price1Cumulative += (
        uint256(FixedPoint.fraction(reserve0, reserve1)._x) *
        timeElapsed
      );
    }
  }

  // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.
  // only gets the first price
  function currentCumulativePrice0(address pair)
    internal
    view
    returns (uint256 price0Cumulative, uint32 blockTimestamp)
  {
    blockTimestamp = currentBlockTimestamp();
    price0Cumulative = IUniswapV2Pair(pair).price0CumulativeLast();

    // if time has elapsed since the last update on the pair, mock the accumulated price values
    (
      uint112 reserve0,
      uint112 reserve1,
      uint32 blockTimestampLast
    ) = IUniswapV2Pair(pair).getReserves();
    require(
      reserve0 != 0 && reserve1 != 0,
      "UniswapV2OracleLibrary::currentCumulativePrice0: Pair has no reserves."
    );
    if (blockTimestampLast != blockTimestamp) {
      // subtraction overflow is desired
      uint32 timeElapsed = blockTimestamp - blockTimestampLast;
      // addition overflow is desired
      // counterfactual
      price0Cumulative += (
        uint256(FixedPoint.fraction(reserve1, reserve0)._x) *
        timeElapsed
      );
    }
  }

  // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.
  // only gets the second price
  function currentCumulativePrice1(address pair)
    internal
    view
    returns (uint256 price1Cumulative, uint32 blockTimestamp)
  {
    blockTimestamp = currentBlockTimestamp();
    price1Cumulative = IUniswapV2Pair(pair).price1CumulativeLast();

    // if time has elapsed since the last update on the pair, mock the accumulated price values
    (
      uint112 reserve0,
      uint112 reserve1,
      uint32 blockTimestampLast
    ) = IUniswapV2Pair(pair).getReserves();
    require(
      reserve0 != 0 && reserve1 != 0,
      "UniswapV2OracleLibrary::currentCumulativePrice1: Pair has no reserves."
    );
    if (blockTimestampLast != blockTimestamp) {
      // subtraction overflow is desired
      uint32 timeElapsed = blockTimestamp - blockTimestampLast;
      // addition overflow is desired
      // counterfactual
      price1Cumulative += (
        uint256(FixedPoint.fraction(reserve0, reserve1)._x) *
        timeElapsed
      );
    }
  }

  function computeAveragePrice(
    uint224 priceCumulativeStart,
    uint224 priceCumulativeEnd,
    uint32 timeElapsed
  ) internal pure returns (FixedPoint.uq112x112 memory priceAverage) {
    // overflow is desired.
    priceAverage = FixedPoint.uq112x112(
      uint224((priceCumulativeEnd - priceCumulativeStart) / timeElapsed)
    );
  }
}

File 5 of 10 : IUniswapV2Pair.sol
pragma solidity >=0.5.0;

interface IUniswapV2Pair {
    event Approval(address indexed owner, address indexed spender, uint value);
    event Transfer(address indexed from, address indexed to, uint value);

    function name() external pure returns (string memory);
    function symbol() external pure returns (string memory);
    function decimals() external pure returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);
    function PERMIT_TYPEHASH() external pure returns (bytes32);
    function nonces(address owner) external view returns (uint);

    function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;

    event Mint(address indexed sender, uint amount0, uint amount1);
    event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
    event Swap(
        address indexed sender,
        uint amount0In,
        uint amount1In,
        uint amount0Out,
        uint amount1Out,
        address indexed to
    );
    event Sync(uint112 reserve0, uint112 reserve1);

    function MINIMUM_LIQUIDITY() external pure returns (uint);
    function factory() external view returns (address);
    function token0() external view returns (address);
    function token1() external view returns (address);
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
    function price0CumulativeLast() external view returns (uint);
    function price1CumulativeLast() external view returns (uint);
    function kLast() external view returns (uint);

    function mint(address to) external returns (uint liquidity);
    function burn(address to) external returns (uint amount0, uint amount1);
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
    function skim(address to) external;
    function sync() external;

    function initialize(address, address) external;
}

File 6 of 10 : UniswapV2Library.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.6.0;

/************************************************************************************************
Originally from https://github.com/Uniswap/uniswap-v2-periphery/blob/master/contracts/libraries/UniswapV2Library.sol

This source code has been modified from the original, which was copied from the github repository
at commit hash 87edfdcaf49ccc52591502993db4c8c08ea9eec0.

Subject to the GPL-3.0 license
*************************************************************************************************/


library UniswapV2Library {
  // returns sorted token addresses, used to handle return values from pairs sorted in this order
  function sortTokens(address tokenA, address tokenB)
    internal
    pure
    returns (address token0, address token1)
  {
    require(tokenA != tokenB, "UniswapV2Library: IDENTICAL_ADDRESSES");
    (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
    require(token0 != address(0), "UniswapV2Library: ZERO_ADDRESS");
  }

  function calculatePair(
    address factory,
    address token0,
    address token1
  ) internal pure returns (address pair) {
    pair = address(
      uint256(
        keccak256(
          abi.encodePacked(
            hex"ff",
            factory,
            keccak256(abi.encodePacked(token0, token1)),
            hex"96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f" // init code hash
          )
        )
      )
    );
  }

  // calculates the CREATE2 address for a pair without making any external calls
  function pairFor(
    address factory,
    address tokenA,
    address tokenB
  ) internal pure returns (address pair) {
    (address token0, address token1) = sortTokens(tokenA, tokenB);
    pair = calculatePair(factory, token0, token1);
  }
}

File 7 of 10 : IndexedPriceMapLibrary.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.6.0;

/* ==========  Internal Libraries  ========== */
import "./PriceLibrary.sol";
import "./KeyIndex.sol";


library IndexedPriceMapLibrary {
  using PriceLibrary for address;
  using KeyIndex for mapping(uint256 => uint256);

/* ==========  Constants  ========== */

  // Period over which prices are observed, each period should have 1 price observation.
  uint256 public constant OBSERVATION_PERIOD = 1 hours;

  // Minimum time elapsed between stored price observations
  uint256 public constant MINIMUM_OBSERVATION_DELAY = 0.5 hours;

/* ==========  Struct  ========== */

  struct IndexedPriceMap {
    mapping(uint256 => uint256) keyIndex;
    mapping(uint256 => PriceLibrary.PriceObservation) priceMap;
  }

/* ========= Utility Functions ========= */

  /**
   * @dev Returns the price key for `timestamp`, which is the hour index.
   */
  function toPriceKey(uint256 timestamp) internal pure returns (uint256/* priceKey */) {
    return timestamp / OBSERVATION_PERIOD;
  }

  /**
   * @dev Returns the number of seconds that have passed since the beginning of the hour.
   */
  function timeElapsedSinceWindowStart(uint256 timestamp) internal pure returns (uint256/* timeElapsed */) {
    return timestamp % OBSERVATION_PERIOD;
  }

/* ========= Mutative Functions ========= */

  /**
   * @dev Writes `observation` to storage if the price can be updated. If it is
   * updated, also marks the price key for the observation as having a value in
   * the key index.
   *
   * Note: The price can be updated if there is none recorded for the current
   * hour 30 minutes have passed since the last price update.
   * Returns a boolean indicating whether the price was updated.
   */
  function writePriceObservation(
    IndexedPriceMap storage indexedPriceMap,
    PriceLibrary.PriceObservation memory observation
  ) internal returns (bool/* didUpdatePrice */) {
    bool canUpdate = sufficientDelaySinceLastPrice(indexedPriceMap, observation.timestamp);
    if (canUpdate) {
      uint256 priceKey = toPriceKey(observation.timestamp);
      canUpdate = indexedPriceMap.keyIndex.markSetKey(priceKey);
      if (canUpdate) {
        indexedPriceMap.priceMap[priceKey] = observation;
      }
    }
    return canUpdate;
  }

/* ========= Price Update View Functions ========= */

  /**
   * @dev Checks whether sufficient time has passed since the beginning of the observation
   * window or since the price recorded in the previous window (if any) for a new price
   * to be recorded.
   */
  function sufficientDelaySinceLastPrice(
    IndexedPriceMap storage indexedPriceMap,
    uint32 newTimestamp
  ) internal view returns (bool/* hasSufficientDelay */) {
    uint256 priceKey = toPriceKey(newTimestamp);
    // If half the observation period has already passed since the beginning of the
    // current window, we can write the price without checking the previous window.
    if (timeElapsedSinceWindowStart(newTimestamp) >= MINIMUM_OBSERVATION_DELAY) {
      return true;
    } else {
      // Verify that at least half the observation period has passed since the last price observation.
      PriceLibrary.PriceObservation storage lastObservation = indexedPriceMap.priceMap[priceKey - 1];
      if (
        lastObservation.timestamp == 0 ||
        newTimestamp - lastObservation.timestamp >= MINIMUM_OBSERVATION_DELAY
      ) {
        return true;
      }
    }
    return false;
  }

  /**
   * @dev Checks if a price can be updated. PriceLibrary can be updated if there is no price
   * observation for the current hour and at least 30 minutes have passed since the
   * observation in the previous hour (if there is one).
   */
  function canUpdatePrice(
    IndexedPriceMap storage indexedPriceMap,
    uint32 newTimestamp
  ) internal view returns (bool/* canUpdatePrice */) {
    uint256 priceKey = toPriceKey(newTimestamp);
    // Verify there is not already a price for the same observation window
    if (indexedPriceMap.keyIndex.hasKey(priceKey)) return false;
    return sufficientDelaySinceLastPrice(indexedPriceMap, newTimestamp);
  }

/* =========  Price View Functions  ========= */

  /**
   * @dev Checks the key index to see if a price is recorded for `priceKey`
   */
  function hasPriceInWindow(
    IndexedPriceMap storage indexedPriceMap,
    uint256 priceKey
  ) internal view returns (bool) {
    return indexedPriceMap.keyIndex.hasKey(priceKey);
  }

  /**
   * @dev Returns the price observation for `priceKey`
   */
  function getPriceInWindow(
    IndexedPriceMap storage indexedPriceMap,
    uint256 priceKey
  ) internal view returns (PriceLibrary.PriceObservation memory) {
    return indexedPriceMap.priceMap[priceKey];
  }

  function getPriceObservationsInRange(
    IndexedPriceMap storage indexedPriceMap,
    uint256 timeFrom,
    uint256 timeTo
  )
    internal
    view
    returns (PriceLibrary.PriceObservation[] memory prices)
  {
    uint256 priceKeyFrom = toPriceKey(timeFrom);
    uint256 priceKeyTo = toPriceKey(timeTo);
    require(priceKeyTo > priceKeyFrom, "IndexedPriceMapLibrary::getPriceObservationsInRange: Invalid time range");
    bytes memory bitPositions = indexedPriceMap.keyIndex.getEncodedSetKeysInRange(priceKeyFrom, priceKeyTo);
    // Divide by 2 because length is in bytes and relative indices are stored as uint16
    uint256 len = bitPositions.length / 2;
    prices = new PriceLibrary.PriceObservation[](len);
    uint256 ptr;
    assembly { ptr := add(bitPositions, 32) }
    for (uint256 i = 0; i < len; i++) {
      uint256 relativeIndex;
      assembly {
        relativeIndex := shr(0xf0, mload(ptr))
        ptr := add(ptr, 2)
      }
      uint256 key = priceKeyFrom + relativeIndex;
      prices[i] = indexedPriceMap.priceMap[key];
    }
  }

  /**
   * @dev Finds the most recent price observation before `timestamp` with a minimum
   * difference in observation times of `minTimeElapsed` and a maximum difference in
   * observation times of `maxTimeElapsed`.
   *
   * Note: `maxTimeElapsed` is only accurate to the nearest hour (rounded down) unless
   * it is below one hour.
   *
   * @param indexedPriceMap Struct with the indexed price mapping for the token.
   * @param timestamp Timestamp to search backwards from.
   * @param minTimeElapsed Minimum time elapsed between price observations.
   * @param maxTimeElapsed Maximum time elapsed between price observations.
   * Only accurate to the nearest hour (rounded down) unless it is below 1 hour.
   */
  function getLastPriceObservation(
    IndexedPriceMap storage indexedPriceMap,
    uint256 timestamp,
    uint256 minTimeElapsed,
    uint256 maxTimeElapsed
  )
    internal
    view
    returns (bool /* foundPrice */, uint256 /* lastPriceKey */)
  {
    uint256 priceKey = toPriceKey(timestamp);
    uint256 windowTimeElapsed = timeElapsedSinceWindowStart(timestamp);
    bool canBeThisWindow = minTimeElapsed <= windowTimeElapsed;
    bool mustBeThisWindow = maxTimeElapsed <= windowTimeElapsed;
    // If the observation window for `timestamp` could include a price observation less than `maxTimeElapsed`
    // older than `timestamp` and the time elapsed since the beginning of the hour for `timestamp` is not higher
    // than `maxTimeElapsed`,  any allowed price must exist in the observation window for `timestamp`.
    if (canBeThisWindow || mustBeThisWindow) {
      PriceLibrary.PriceObservation storage observation = indexedPriceMap.priceMap[priceKey];
      uint32 obsTimestamp = observation.timestamp;
      if (
        obsTimestamp != 0 &&
        timestamp > obsTimestamp &&
        timestamp - obsTimestamp <= maxTimeElapsed &&
        timestamp - obsTimestamp >= minTimeElapsed
      ) {
        return (true, priceKey);
      }
      if (mustBeThisWindow) {
        return (false, 0);
      }
    }

    uint256 beginSearchTime = timestamp - minTimeElapsed;
    priceKey = toPriceKey(beginSearchTime);
    uint256 maxDistance = toPriceKey(maxTimeElapsed);
    return indexedPriceMap.keyIndex.findLastSetKey(priceKey, maxDistance);
  }
}

File 8 of 10 : KeyIndex.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.6.0;

/* ==========  Internal Libraries  ========== */
import "./Bits.sol";


/**
 * @dev Library for indexing keys stored in a sequential mapping for easier
 * queries.
 *
 * Every set of 256 keys in the value map is assigned a single index which
 * records set values as bits, where 1 indicates the map has a value at a given
 * key and 0 indicates it does not.
 *
 * The 'value map' is the map which stores the values with sequential keys.
 * The 'key index' is the map which records the indices for every 256 keys
 * in the value map.
 *
 * The 'key index' is the mapping which stores the indices for each 256 values
 * in the map. For example, the key '256' in the value map would have a key
 * in the key index of `1`, where the 0th bit in the index records whether a
 * value is set in the value map .
 */
library KeyIndex {
  using Bits for uint256;
  using Bits for bytes;

/* ========= Utility Functions ========= */

  /**
   * @dev Compute the map key for a given index key and position.
   * Multiplies indexKey by 256 and adds indexPosition.
   */
  function toMapKey(uint256 indexKey, uint256 indexPosition) internal pure returns (uint256) {
    return (indexKey * 256) + indexPosition;
  }

  /**
   * @dev Returns the key in the key index which stores the index for the 256-bit
   * index which includes `mapKey` and the position in the index for that key.
   */
  function indexKeyAndPosition(uint256 mapKey)
    internal
    pure
    returns (uint256 indexKey, uint256 indexPosition)
  {
    indexKey = mapKey / 256;
    indexPosition = mapKey % 256;
  }

/* ========= Mutative Functions ========= */

  /**
   * @dev Sets a bit at the position in `indexMap` corresponding to `mapKey` if the
   * bit is not already set.
   *
   * @param keyIndex Mapping with indices of set keys in the value map
   * @param mapKey Position in the value map to mark as set
   */
  function markSetKey(
    mapping(uint256 => uint256) storage keyIndex,
    uint256 mapKey
  ) internal returns (bool /* didSetKey */) {
    (uint256 indexKey, uint256 indexPosition) = indexKeyAndPosition(mapKey);
    // console.log("IPOS", indexPosition);
    uint256 localIndex = keyIndex[indexKey];
    bool canSetKey = !localIndex.bitSet(indexPosition);
    if (canSetKey) {
      keyIndex[indexKey] = localIndex.setBit(indexPosition);
    }
    return canSetKey;
  }

/* ========= View Functions ========= */

  /**
   * @dev Returns a boolean indicating whether a value is stored for `mapKey` in the map index.
   */
  function hasKey(
    mapping(uint256 => uint256) storage keyIndex,
    uint256 mapKey
  ) internal view returns (bool) {
    (uint256 indexKey, uint256 indexPosition) = indexKeyAndPosition(mapKey);
    uint256 localIndex = keyIndex[indexKey];
    if (localIndex == 0) return false;
    return localIndex.bitSet(indexPosition);
  }

  /**
   * @dev Returns a packed uint16 array with the offsets of all set keys
   * between `mapKeyFrom` and `mapKeyTo`. Offsets are relative to `mapKeyFrom`
   */
  function getEncodedSetKeysInRange(
    mapping(uint256 => uint256) storage keyIndex,
    uint256 mapKeyFrom,
    uint256 mapKeyTo
  ) internal view returns (bytes memory bitPositions) {
    uint256 rangeSize = mapKeyTo - mapKeyFrom;
    (uint256 indexKeyStart, uint256 indexPositionStart) = indexKeyAndPosition(mapKeyFrom);
    (uint256 indexKeyEnd, uint256 indexPositionEnd) = indexKeyAndPosition(mapKeyTo);
    // Expand memory too accomodate the maximum number of bits that could be found
    // Length is 2*range because values are stored as uint16s
    // 30 is added because 32 bytes are stored at a time and this would go past rangeSize*2
    // if most bits are set
    bitPositions = new bytes((2 * rangeSize) + 30);
    // Set the length to 0, as it is used by the `writeSetBits` fn
    assembly { mstore(bitPositions, 0) }
    uint256 indexKey = indexKeyStart;
    // Clear the bits before `indexPositionStart` so they are not included in the search result
    uint256 localIndex = keyIndex[indexKey].clearBitsBefore(indexPositionStart);
    uint16 offset = 0;
    // Check each index until the last one is reached
    while (indexKey < indexKeyEnd) {
      // Relative index is set by adding provided `offset` to the bit index
      bitPositions.writeSetBits(localIndex, offset);
      indexKey += 1;
      localIndex = keyIndex[indexKey];
      offset += 256;
    }
    // Clear the bits after `indexPositionEnd` before searching for set bits
    localIndex = localIndex.clearBitsAfter(indexPositionEnd);
    bitPositions.writeSetBits(localIndex, offset);
  }

  /**
   * @dev Find the most recent position before `mapKey` which the index map records
   * as having a set value. Returns the key in the value map for that position.
   *
   * @param keyIndex Mapping with indices of set keys in the value map
   * @param mapKey Position in the value map to look behind
   * @param maxDistance Maximum distance between the found value and `mapKey`
   */
  function findLastSetKey(
    mapping(uint256 => uint256) storage keyIndex,
    uint256 mapKey,
    uint256 maxDistance
  )
    internal
    view
    returns (bool/* found */, uint256/* mapKey */)
  {
    (uint256 indexKey, uint256 indexPosition) = indexKeyAndPosition(mapKey);
    uint256 distance = 0;
    bool found;
    uint256 position;
    uint256 localIndex;
    // If the position is 0, we must go to the previous index
    if (indexPosition == 0) {
      require(indexKey != 0, "KeyIndex::findLastSetKey:Can not query value prior to 0.");
      indexKey -= 1;
      distance = 1;
    } else {
      localIndex = keyIndex[indexKey];
      (found, position) = localIndex.nextLowestBitSet(indexPosition);
      if (found) {
        distance += indexPosition - position;
      } else {
        distance += indexPosition + 1;
        indexKey -= 1;
      }
    }

    while (!found && distance <= maxDistance) {
      localIndex = keyIndex[indexKey];
      if (localIndex == 0) {
        if (indexKey == 0) return (false, 0);
        distance += 256;
        indexKey -= 1;
      } else {
        position = localIndex.highestBitSet();
        distance += 255 - position;
        found = true;
      }
    }
    if (distance > maxDistance) {
      return (false, 0);
    }
    return (true, toMapKey(indexKey, position));
  }

  /**
   * @dev Find the next position after `mapKey` which the index map records as
   * having a set value. Returns the key in the value map for that position.
   *
   * @param keyIndex Mapping with indices of set values in the value map
   * @param mapKey Position in the value map to look ahead
   * @param maxDistance Maximum distance between the found value and `mapKey`
   */
  function findNextSetKey(
    mapping(uint256 => uint256) storage keyIndex,
    uint256 mapKey,
    uint256 maxDistance
  )
    internal
    view
    returns (bool/* found */, uint256/* mapKey */)
  {
    (uint256 indexKey, uint256 indexPosition) = indexKeyAndPosition(mapKey);
    uint256 distance = 0;
    bool found;
    uint256 position;
    uint256 localIndex;
    if (indexPosition == 255) {
      indexKey += 1;
      position = indexPosition;
      distance = 1;
    } else {
      localIndex = keyIndex[indexKey];
      (found, position) = localIndex.nextHighestBitSet(indexPosition);
      if (found) {
        distance += position - indexPosition;
      } else {
        distance += 256 - indexPosition;
        indexKey += 1;
      }
    }
    while (!found && distance <= maxDistance) {
      localIndex = keyIndex[indexKey];
      if (localIndex == 0) {
        distance += 256;
        indexKey += 1;
      } else {
        position = localIndex.lowestBitSet();
        distance += position;
        found = true;
      }
    }
    if (distance > maxDistance) {
      return (false, 0);
    }
    return (true, toMapKey(indexKey, position));
  }
}

File 9 of 10 : Bits.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;


library Bits {
  uint256 internal constant ONE = uint256(1);
  uint256 internal constant ONES = uint256(~0);

  /**
   * @dev Sets the bit at the given 'index' in 'self' to '1'.
   * Returns the modified value.
   */
  function setBit(uint256 self, uint256 index) internal pure returns (uint256) {
    return self | (ONE << index);
  }

  /**
   * @dev Returns a boolean indicating whether the bit at the given `index` in `self` is set.
   */
  function bitSet(uint256 self, uint256 index) internal pure returns (bool) {
    return (self >> index) & 1 == 1;
  }

  /**
    * @dev Clears all bits in the exclusive range [index:255]
    */
  function clearBitsAfter(uint256 self, uint256 index) internal pure returns (uint256) {
    return self & (ONES >> (255 - index));
  }

  /**
    * @dev Clears bits in the exclusive range [0:index]
    */
  function clearBitsBefore(uint256 self, uint256 index) internal pure returns (uint256) {
    return self & (ONES << (index));
  }

  /**
   * @dev Writes the index of every set bit in `val` as a uint16 in `bitPositions`.
   * Adds `offset` to the stored bit index.
   *
   * `bitPositions` must have a length equal to twice the maximum number of bits that
   * could be found plus 31. Each index is stored as a uint16 to accomodate `offset`
   *  because this is used in functions which would otherwise need expensive methods
   * to handle relative indices in multi-integer searches.
   * The specified length ensures that solc will handle memory allocation, and the
   * addition of 31 allows us to store whole words at a time.
   * After being declared, the actual length stored in memory must be set to 0 with:
   * `assembly { mstore(bitPositions, 0) }` because the length is used to count found bits.
   *
   * @param bitPositions Packed uint16 array for positions of set bits
   * @param val Value to search set bits in
   * @param offset Value added to the stored position, used to simplify large searches.
   */
  function writeSetBits(bytes memory bitPositions, uint256 val, uint16 offset) internal pure {
    if (val == 0) return;

    assembly {
      // Read the current length, which is the number of stored bytes
      let len := mload(bitPositions)
      // Set the starting pointer by adding the length to the bytes data pointer
      // This does not change and is later used to compute the new length
      let startPtr := add(add(bitPositions, 32), len)
      // Set the variable pointer which is used to track where to write memory values
      let ptr := startPtr
      // Increment the number of bits to shift until the shifted integer is 0
      // Add 3 to the index each loop because that is the number of bits being checked
      // at a time.
      for {let i := 0} gt(shr(i, val), 0) {i := add(i, 3)} {
        // Loop until the last 8 bits are not all 0
        for {} eq(and(shr(i, val), 255), 0) {i := add(i, 8)} {}
        // Take only the last 3  bits
        let x := and(shr(i, val), 7)
        // Use a switch statement as a lookup table with every possible combination of 3 bits.
        switch x
          case 0 {}// no bits set
          case 1 {// bit 0 set
            // shift left 240 bits to write uint16, increment ptr by 2 bytes
            mstore(ptr, shl(0xf0, add(i, offset)))
            ptr := add(ptr, 2)
          }
          case 2 {// bit 1 set
            // shift left 240 bits to write uint16, increment ptr by 2 bytes
            mstore(ptr, shl(0xf0, add(add(i, 1), offset)))
            ptr := add(ptr, 2)
          }
          case 3 {// bits 0,1 set
            // shift first left 240 bits and second 224 to write two uint16s
            // increment ptr by 4 bytes
            mstore(
              ptr,
              or(// use OR to avoid multiple memory writes
                shl(0xf0, add(i, offset)),
                shl(0xe0, add(add(i, 1), offset))
              )
            )
            ptr := add(ptr, 4)
          }
          case 4 {// bit 2 set
            // shift left 240 bits to write uint16, increment ptr by 2 bytes
            mstore(ptr, shl(0xf0, add(add(i, 2), offset)))
            ptr := add(ptr, 2)
          }
          case 5 {// 5: bits 0,2 set
            // shift first left 240 bits and second 224 bits to write two uint16s
            mstore(
              ptr,
              or(// use OR to avoid multiple memory writes
                shl(0xf0, add(i, offset)),
                shl(0xe0, add(add(i, 2), offset))
              )
            )

            ptr := add(ptr, 4)// increment ptr by 4 bytes
          }
          case 6 {// bits 1,2 set
            // shift first left 240 bits and second 224 to write two uint16s
            mstore(
              ptr,
              or(// use OR to avoid multiple memory writes
                shl(0xf0, add(add(i, 1), offset)),
                shl(0xe0, add(add(i, 2), offset))
              )
            )
            ptr := add(ptr, 4)// increment ptr by 4 bytes
          }
          case 7 {//bits 0,1,2 set
            // shift first left 240 bits, second 224, third 208 to write three uint16s
            mstore(
              ptr,
              or(// use OR to avoid multiple memory writes
                shl(0xf0, add(i, offset)),
                or(
                  shl(0xe0, add(add(i, 1), offset)),
                  shl(0xd0, add(add(i, 2), offset))
                )
              )
            )
            ptr := add(ptr, 6)// increment ptr by 6 bytes
          }
      }
      // subtract current pointer from initial to get byte length
      let newLen := sub(ptr, startPtr)
      // write byte length
      mstore(bitPositions, add(len, newLen))
    }
  }

  /**
   * @dev Returns the index of the highest bit set in `self`.
   * Note: Requires that `self != 0`
   */
  function highestBitSet(uint256 self) internal pure returns (uint256 r) {
    uint256 x = self;
    require (x > 0, "Bits::highestBitSet: Value 0 has no bits set");
    if (x >= 0x100000000000000000000000000000000) {x >>= 128; r += 128;}
    if (x >= 0x10000000000000000) {x >>= 64; r += 64;}
    if (x >= 0x100000000) {x >>= 32; r += 32;}
    if (x >= 0x10000) {x >>= 16; r += 16;}
    if (x >= 0x100) {x >>= 8; r += 8;}
    if (x >= 0x10) {x >>= 4; r += 4;}
    if (x >= 0x4) {x >>= 2; r += 2;}
    if (x >= 0x2) r += 1; // No need to shift x anymore
  }

  /**
   * @dev Returns the index of the lowest bit set in `self`.
   * Note: Requires that `self != 0`
   */
  function lowestBitSet(uint256 self) internal pure returns (uint256 _z) {
    require (self > 0, "Bits::lowestBitSet: Value 0 has no bits set");
    uint256 _magic = 0x00818283848586878898a8b8c8d8e8f929395969799a9b9d9e9faaeb6bedeeff;
    uint256 val = (self & -self) * _magic >> 248;
    uint256 _y = val >> 5;
    _z = (
      _y < 4
        ? _y < 2
          ? _y == 0
            ? 0x753a6d1b65325d0c552a4d1345224105391a310b29122104190a110309020100
            : 0xc976c13bb96e881cb166a933a55e490d9d56952b8d4e801485467d2362422606
          : _y == 2
            ? 0xe39ed557db96902cd38ed14fad815115c786af479b7e83247363534337271707
            : 0xf7cae577eec2a03cf3bad76fb589591debb2dd67e0aa9834bea6925f6a4a2e0e
        : _y < 6
          ? _y == 4
            ? 0xc8c0b887b0a8a4489c948c7f847c6125746c645c544c444038302820181008ff
            : 0xf6e4ed9ff2d6b458eadcdf97bd91692de2d4da8fd2d0ac50c6ae9a8272523616
          : _y == 6
            ? 0xf5ecf1b3e9debc68e1d9cfabc5997135bfb7a7a3938b7b606b5b4b3f2f1f0ffe
            : 0xf8f9cbfae6cc78fbefe7cdc3a1793dfcf4f0e8bbd8cec470b6a28a7a5a3e1efd
    );
    _z >>= (val & 0x1f) << 3;
    return _z & 0xff;
  }

  /**
   * @dev Returns a boolean indicating whether `bit` is the highest set bit
   * in the integer and the index of the next lowest set bit if it is not.
   */
  function nextLowestBitSet(uint256 self, uint256 bit)
    internal
    pure
    returns (bool haveValueBefore, uint256 previousBit)
  {
    uint256 val = self << (256 - bit);
    if (val == 0) {
      return (false, 0);
    }
    return (true, (highestBitSet(val) - (256 - bit)));
  }

  /**
   * @dev Returns a boolean indicating whether `bit` is the lowest set bit
   * in the integer and the index of the next highest set bit if it is not.
   */
  function nextHighestBitSet(uint256 self, uint256 bit)
    internal
    pure
    returns (bool haveValueAfter, uint256 nextBit)
  {
    uint256 val = self >> (bit + 1);
    if (val == 0) {
      return (false, 0);
    }
    return (true, lowestBitSet(val) + (bit + 1));
  }
}

File 10 of 10 : IIndexedUniswapV2Oracle.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

/* ==========  Libraries  ========== */
import "../lib/PriceLibrary.sol";
import "../lib/FixedPoint.sol";


interface IIndexedUniswapV2Oracle {
/* ==========  Mutative Functions  ========== */

  function updatePrice(address token) external returns (bool);

  function updatePrices(address[] calldata tokens) external returns (bool[] memory);

/* ==========  Meta Price Queries  ========== */

  function hasPriceObservationInWindow(address token, uint256 priceKey) external view returns (bool);

  function getPriceObservationInWindow(
    address token, uint256 priceKey
  ) external view returns (PriceLibrary.PriceObservation memory);

  function getPriceObservationsInRange(
    address token, uint256 timeFrom, uint256 timeTo
  ) external view returns (PriceLibrary.PriceObservation[] memory prices);

/* ==========  Price Update Queries  ========== */

  function canUpdatePrice(address token) external view returns (bool);

  function canUpdatePrices(address[] calldata tokens) external view returns (bool[] memory);

/* ==========  Price Queries: Singular  ========== */

  function computeTwoWayAveragePrice(
    address token, uint256 minTimeElapsed, uint256 maxTimeElapsed
  ) external view returns (PriceLibrary.TwoWayAveragePrice memory);

  function computeAverageTokenPrice(
    address token, uint256 minTimeElapsed, uint256 maxTimeElapsed
  ) external view returns (FixedPoint.uq112x112 memory);

  function computeAverageEthPrice(
    address token, uint256 minTimeElapsed, uint256 maxTimeElapsed
  ) external view returns (FixedPoint.uq112x112 memory);

/* ==========  Price Queries: Multiple  ========== */

  function computeTwoWayAveragePrices(
    address[] calldata tokens,
    uint256 minTimeElapsed,
    uint256 maxTimeElapsed
  ) external view returns (PriceLibrary.TwoWayAveragePrice[] memory);

  function computeAverageTokenPrices(
    address[] calldata tokens,
    uint256 minTimeElapsed,
    uint256 maxTimeElapsed
  ) external view returns (FixedPoint.uq112x112[] memory);

  function computeAverageEthPrices(
    address[] calldata tokens,
    uint256 minTimeElapsed,
    uint256 maxTimeElapsed
  ) external view returns (FixedPoint.uq112x112[] memory);

/* ==========  Value Queries: Singular  ========== */

  function computeAverageEthForTokens(
    address token,
    uint256 tokenAmount,
    uint256 minTimeElapsed,
    uint256 maxTimeElapsed
  ) external view returns (uint144);

  function computeAverageTokensForEth(
    address token,
    uint256 wethAmount,
    uint256 minTimeElapsed,
    uint256 maxTimeElapsed
  ) external view returns (uint144);

/* ==========  Value Queries: Multiple  ========== */

  function computeAverageEthForTokens(
    address[] calldata tokens,
    uint256[] calldata tokenAmounts,
    uint256 minTimeElapsed,
    uint256 maxTimeElapsed
  ) external view returns (uint144[] memory);

  function computeAverageTokensForEth(
    address[] calldata tokens,
    uint256[] calldata wethAmounts,
    uint256 minTimeElapsed,
    uint256 maxTimeElapsed
  ) external view returns (uint144[] memory);
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"uniswapFactory","type":"address"},{"internalType":"address","name":"weth","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"canUpdatePrice","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"canUpdatePrices","outputs":[{"internalType":"bool[]","name":"canUpdateArr","type":"bool[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"tokenAmounts","type":"uint256[]"},{"internalType":"uint256","name":"minTimeElapsed","type":"uint256"},{"internalType":"uint256","name":"maxTimeElapsed","type":"uint256"}],"name":"computeAverageEthForTokens","outputs":[{"internalType":"uint144[]","name":"averageValuesInWETH","type":"uint144[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"uint256","name":"minTimeElapsed","type":"uint256"},{"internalType":"uint256","name":"maxTimeElapsed","type":"uint256"}],"name":"computeAverageEthForTokens","outputs":[{"internalType":"uint144","name":"","type":"uint144"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"minTimeElapsed","type":"uint256"},{"internalType":"uint256","name":"maxTimeElapsed","type":"uint256"}],"name":"computeAverageEthPrice","outputs":[{"components":[{"internalType":"uint224","name":"_x","type":"uint224"}],"internalType":"struct FixedPoint.uq112x112","name":"priceAverage","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256","name":"minTimeElapsed","type":"uint256"},{"internalType":"uint256","name":"maxTimeElapsed","type":"uint256"}],"name":"computeAverageEthPrices","outputs":[{"components":[{"internalType":"uint224","name":"_x","type":"uint224"}],"internalType":"struct FixedPoint.uq112x112[]","name":"averagePrices","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"minTimeElapsed","type":"uint256"},{"internalType":"uint256","name":"maxTimeElapsed","type":"uint256"}],"name":"computeAverageTokenPrice","outputs":[{"components":[{"internalType":"uint224","name":"_x","type":"uint224"}],"internalType":"struct FixedPoint.uq112x112","name":"priceAverage","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256","name":"minTimeElapsed","type":"uint256"},{"internalType":"uint256","name":"maxTimeElapsed","type":"uint256"}],"name":"computeAverageTokenPrices","outputs":[{"components":[{"internalType":"uint224","name":"_x","type":"uint224"}],"internalType":"struct FixedPoint.uq112x112[]","name":"averagePrices","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"wethAmounts","type":"uint256[]"},{"internalType":"uint256","name":"minTimeElapsed","type":"uint256"},{"internalType":"uint256","name":"maxTimeElapsed","type":"uint256"}],"name":"computeAverageTokensForEth","outputs":[{"internalType":"uint144[]","name":"averageValuesInWETH","type":"uint144[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"wethAmount","type":"uint256"},{"internalType":"uint256","name":"minTimeElapsed","type":"uint256"},{"internalType":"uint256","name":"maxTimeElapsed","type":"uint256"}],"name":"computeAverageTokensForEth","outputs":[{"internalType":"uint144","name":"","type":"uint144"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"minTimeElapsed","type":"uint256"},{"internalType":"uint256","name":"maxTimeElapsed","type":"uint256"}],"name":"computeTwoWayAveragePrice","outputs":[{"components":[{"internalType":"uint224","name":"priceAverage","type":"uint224"},{"internalType":"uint224","name":"ethPriceAverage","type":"uint224"}],"internalType":"struct PriceLibrary.TwoWayAveragePrice","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256","name":"minTimeElapsed","type":"uint256"},{"internalType":"uint256","name":"maxTimeElapsed","type":"uint256"}],"name":"computeTwoWayAveragePrices","outputs":[{"components":[{"internalType":"uint224","name":"priceAverage","type":"uint224"},{"internalType":"uint224","name":"ethPriceAverage","type":"uint224"}],"internalType":"struct PriceLibrary.TwoWayAveragePrice[]","name":"prices","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"priceKey","type":"uint256"}],"name":"getPriceObservationInWindow","outputs":[{"components":[{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"uint224","name":"priceCumulativeLast","type":"uint224"},{"internalType":"uint224","name":"ethPriceCumulativeLast","type":"uint224"}],"internalType":"struct PriceLibrary.PriceObservation","name":"observation","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"timeFrom","type":"uint256"},{"internalType":"uint256","name":"timeTo","type":"uint256"}],"name":"getPriceObservationsInRange","outputs":[{"components":[{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"uint224","name":"priceCumulativeLast","type":"uint224"},{"internalType":"uint224","name":"ethPriceCumulativeLast","type":"uint224"}],"internalType":"struct PriceLibrary.PriceObservation[]","name":"prices","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"priceKey","type":"uint256"}],"name":"hasPriceObservationInWindow","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"updatePrice","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"updatePrices","outputs":[{"internalType":"bool[]","name":"pricesUpdated","type":"bool[]"}],"stateMutability":"nonpayable","type":"function"}]

60c06040523480156200001157600080fd5b50604051620031cb380380620031cb833981016040819052620000349162000053565b6001600160601b0319606092831b8116608052911b1660a052620000aa565b6000806040838503121562000066578182fd5b8251620000738162000091565b6020840151909250620000868162000091565b809150509250929050565b6001600160a01b0381168114620000a757600080fd5b50565b60805160601c60a05160601c6130b16200011a6000398061061052806109c05280610a495280610ac15280610cc85280610d445280610e2b5280610ea15280610fde528061108f5250806105ed528061099d5280610a9e5280610d225280610e7e528061106c52506130b16000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80637c906a2a116100a257806396e85ced1161007157806396e85ced14610265578063bf6dd82e14610278578063c735e38c1461028b578063cdee7f6e146102ab578063ffd97b6f146102be5761010b565b80637c906a2a1461020c5780637e5296e01461021f57806388a14c3c1461023f5780639691b116146102525761010b565b80634f2acedf116100de5780634f2acedf1461019957806357653615146101b95780635acd73d7146101d9578063768d2c19146101ec5761010b565b806310bc482a146101105780632d726197146101395780633a9d6535146101595780634506006014610179575b600080fd5b61012361011e36600461254f565b6102de565b6040516101309190612982565b60405180910390f35b61014c6101473660046126aa565b61030f565b60405161013091906128ff565b61016c610167366004612579565b6103f1565b604051610130919061303c565b61018c610187366004612630565b610430565b6040516101309190612941565b6101ac6101a73660046125ac565b610551565b604051610130919061304f565b6101cc6101c7366004612579565b6105a9565b604051610130919061302e565b6101236101e7366004612534565b6105de565b6101ff6101fa3660046126aa565b610676565b60405161013091906128b2565b61018c61021a366004612630565b610743565b61023261022d3660046125f1565b610845565b604051610130919061282a565b61023261024d3660046125f1565b6108e6565b61016c610260366004612579565b610a10565b610123610273366004612534565b610a45565b6101ac6102863660046125ac565b610b1d565b61029e61029936600461254f565b610b54565b6040516101309190613020565b61014c6102b93660046126aa565b610bab565b6102d16102cc366004612579565b610c78565b6040516101309190612870565b6001600160a01b0382166000908152602081905260408120610306908363ffffffff610cac16565b90505b92915050565b606082828181101561033c5760405162461bcd60e51b815260040161033390612ab5565b60405180910390fd5b85806001600160401b038111801561035357600080fd5b5060405190808252806020026020018201604052801561038d57816020015b61037a612480565b8152602001906001900390816103725790505b50935060005b818110156103e5576103c68989838181106103aa57fe5b90506020020160208101906103bf9190612534565b8888610cbe565b8582815181106103d257fe5b6020908102919091010152600101610393565b50505050949350505050565b6103f9612480565b82828181101561041b5760405162461bcd60e51b815260040161033390612ab5565b610426868686610e21565b9695505050505050565b60608282818110156104545760405162461bcd60e51b815260040161033390612ab5565b878681146104745760405162461bcd60e51b815260040161033390612c4c565b806001600160401b038111801561048a57600080fd5b506040519080825280602002602001820160405280156104b4578160200160208202803683370190505b50935060005b81811015610543576105176105128a8a848181106104d457fe5b905060200201356105068e8e868181106104ea57fe5b90506020020160208101906104ff9190612534565b8b8b610cbe565b9063ffffffff610f6e16565b610fcd565b85828151811061052357fe5b6001600160901b03909216602092830291909101909101526001016104ba565b505050509695505050505050565b60008282818110156105755760405162461bcd60e51b815260040161033390612ab5565b61057d612480565b610588888787610cbe565b905061059d610512828963ffffffff610f6e16565b98975050505050505050565b6105b1612492565b8282818110156105d35760405162461bcd60e51b815260040161033390612ab5565b610426868686610fd4565b600061063a6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016837f000000000000000000000000000000000000000000000000000000000000000063ffffffff61118816565b61064657506000610671565b6001600160a01b038216600090815260208190526040902061066e904263ffffffff61123e16565b90505b919050565b606082828181101561069a5760405162461bcd60e51b815260040161033390612ab5565b85806001600160401b03811180156106b157600080fd5b506040519080825280602002602001820160405280156106eb57816020015b6106d8612492565b8152602001906001900390816106d05790505b50935060005b818110156103e55761072489898381811061070857fe5b905060200201602081019061071d9190612534565b8888610fd4565b85828151811061073057fe5b60209081029190910101526001016106f1565b60608282818110156107675760405162461bcd60e51b815260040161033390612ab5565b878681146107875760405162461bcd60e51b815260040161033390612e14565b806001600160401b038111801561079d57600080fd5b506040519080825280602002602001820160405280156107c7578160200160208202803683370190505b50935060005b81811015610543576108196105128a8a848181106107e757fe5b905060200201356105068e8e868181106107fd57fe5b90506020020160208101906108129190612534565b8b8b610e21565b85828151811061082557fe5b6001600160901b03909216602092830291909101909101526001016107cd565b606081806001600160401b038111801561085e57600080fd5b50604051908082528060200260200182016040528015610888578160200160208202803683370190505b50915060005b818110156108de576108ba8585838181106108a557fe5b90506020020160208101906102739190612534565b8382815181106108c657fe5b9115156020928302919091019091015260010161088e565b505092915050565b606081806001600160401b03811180156108ff57600080fd5b50604051908082528060200260200182016040528015610929578160200160208202803683370190505b50915060005b818110156108de57600085858381811061094557fe5b905060200201602081019061095a9190612534565b6001600160a01b038116600090815260208190526040812091925090610986904263ffffffff61123e16565b90508080156109ea57506109ea6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016837f000000000000000000000000000000000000000000000000000000000000000063ffffffff61118816565b8584815181106109f657fe5b91151560209283029190910190910152505060010161092f565b610a18612480565b828281811015610a3a5760405162461bcd60e51b815260040161033390612ab5565b610426868686610cbe565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161415610a8957506001610671565b610a916124a9565b610aeb6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016847f000000000000000000000000000000000000000000000000000000000000000063ffffffff61127b16565b6001600160a01b0384166000908152602081905260409020909150610b16908263ffffffff61135e16565b9392505050565b6000828281811015610b415760405162461bcd60e51b815260040161033390612ab5565b610b49612480565b610588888787610e21565b610b5c6124a9565b6001600160a01b0383166000908152602081905260409020610b84908363ffffffff61141216565b805190915063ffffffff166103095760405162461bcd60e51b815260040161033390612eda565b6060828281811015610bcf5760405162461bcd60e51b815260040161033390612ab5565b85806001600160401b0381118015610be657600080fd5b50604051908082528060200260200182016040528015610c2057816020015b610c0d612480565b815260200190600190039081610c055790505b50935060005b818110156103e557610c59898983818110610c3d57fe5b9050602002016020810190610c529190612534565b8888610e21565b858281518110610c6557fe5b6020908102919091010152600101610c26565b6001600160a01b0383166000908152602081905260409020606090610ca490848463ffffffff61146816565b949350505050565b6000610306838363ffffffff6115a816565b610cc6612480565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b03161415610d1257610d0b6001806115eb565b9050610b16565b600080610d6f6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000008863ffffffff61165f16565b6001600160a01b0388166000908152602081905260408120929450909250908190610da79063ffffffff808716908a908a906116cb16565b9150915081610dc85760405162461bcd60e51b815260040161033390612b9a565b6001600160a01b03881660009081526020818152604080832084845260019081019092529091208054918101549091610e149163ffffffff909116906001600160e01b031687876117c5565b9998505050505050505050565b610e29612480565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b03161415610e6e57610d0b6001806115eb565b600080610ecb6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016877f000000000000000000000000000000000000000000000000000000000000000063ffffffff61165f16565b6001600160a01b0388166000908152602081905260408120929450909250908190610f039063ffffffff808716908a908a906116cb16565b9150915081610f245760405162461bcd60e51b815260040161033390612b2b565b6001600160a01b03881660009081526020818152604080832084845260010190915290208054610e149063ffffffff81169064010000000090046001600160e01b031687876117c5565b610f766124c9565b6000821580610f9c57505082516001600160e01b031682810290838281610f9957fe5b04145b610fb85760405162461bcd60e51b815260040161033390612e97565b60408051602081019091529081529392505050565b5160701c90565b610fdc612492565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316141561105757604051806040016040528061102b60016117e3565b516001600160e01b0316815260200161104460016117e3565b516001600160e01b031690529050610b16565b61105f6124a9565b6110b96001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016867f000000000000000000000000000000000000000000000000000000000000000063ffffffff61127b16565b80516001600160a01b03871660009081526020819052604081209293509182916110f1919063ffffffff90811690899089906116cb16565b91509150816111125760405162461bcd60e51b815260040161033390612a45565b61111a6124a9565b506001600160a01b03871660009081526020818152604080832084845260019081018352928190208151606081018352815463ffffffff80821683526001600160e01b036401000000009092048216958301959095529190940154169083015261059d908290869061180e16565b60008061119685858561187d565b9050600080826001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b1580156111d457600080fd5b505afa1580156111e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061120c91906126f8565b5091509150816001600160701b031660001415801561123357506001600160701b03811615155b979650505050505050565b6000806112508363ffffffff1661189b565b9050611262848263ffffffff6115a816565b15611271576000915050610309565b610ca484846118a3565b6112836124a9565b600080611290858561192c565b9150915060006112a18784846119b6565b905060008060006112b184611a13565b925092509250886001600160a01b0316866001600160a01b031614156113115760405180606001604052808263ffffffff168152602001846001600160e01b03168152602001836001600160e01b03168152509650505050505050610b16565b60405180606001604052808263ffffffff168152602001836001600160e01b03168152602001846001600160e01b03168152509650505050505050610b16565b5050505050509392505050565b60008061136f8484600001516118a3565b9050801561030657600061138c846000015163ffffffff1661189b565b905061139e858263ffffffff611c2616565b9150811561140a57600081815260018681016020908152604092839020875181549289015163ffffffff1990931663ffffffff91821617166401000000006001600160e01b0393841602178155928701519290910180546001600160e01b031916929091169190911790555b509392505050565b61141a6124a9565b506000908152600191820160209081526040918290208251606081018452815463ffffffff8116825264010000000090046001600160e01b0390811693820193909352930154169082015290565b606060006114758461189b565b905060006114828461189b565b90508181116114a35760405162461bcd60e51b815260040161033390612da7565b60606114b687848463ffffffff611c8b16565b9050600060028251816114c557fe5b049050806001600160401b03811180156114de57600080fd5b5060405190808252806020026020018201604052801561151857816020015b6115056124a9565b8152602001906001900390816114fd5790505b5094506020820160005b8281101561135157815160f01c86810160008181526001808e0160209081526040928390208351606081018552815463ffffffff811682526001600160e01b03640100000000909104811693820193909352920154169181019190915289516002909501948a908590811061159357fe5b60209081029190910101525050600101611522565b60008060006115b684611d92565b6000828152602088905260409020549193509150806115db5760009350505050610309565b610426818363ffffffff611da016565b6115f3612480565b6000826001600160701b03161161161c5760405162461bcd60e51b815260040161033390612fe9565b6040805160208101909152806001600160701b038416600160701b600160e01b03607087901b168161164a57fe5b046001600160e01b0316815250905092915050565b60008060008061166f868661192c565b9150915060006116808884846119b6565b9050866001600160a01b0316836001600160a01b031614156116b7576000806116a883611daa565b975095506116c3945050505050565b6000806116a883611f25565b935093915050565b60008060006116d98661189b565b905060006116e687612086565b9050808611158186111581806116f95750805b1561178557600084815260018b0160205260409020805463ffffffff16801580159061172a57508063ffffffff168b115b801561173e5750888163ffffffff168c0311155b80156117525750898163ffffffff168c0310155b1561176957600186975097505050505050506117bc565b82156117825750600096508695506117bc945050505050565b50505b8789036117918161189b565b9450600061179e8961189b565b90506117b18c878363ffffffff61208e16565b975097505050505050505b94509492505050565b6117cd612480565b6117da84838786036121c6565b95945050505050565b6117eb612480565b50604080516020810190915260709190911b600160701b600160e01b0316815290565b611816612492565b8251825103611823612480565b61183685602001518560200151846121c6565b9050611840612480565b61185386604001518660400151856121c6565b6040805180820190915292516001600160e01b039081168452905116602083015250949350505050565b600080600061188c858561192c565b915091506104268683836119b6565b610e10900490565b6000806118b58363ffffffff1661189b565b90506107086118c98463ffffffff16612086565b106118d8576001915050610309565b600019810160009081526001850160205260409020805463ffffffff1615806119115750805461070863ffffffff918216860390911610155b1561192157600192505050610309565b506000949350505050565b600080826001600160a01b0316846001600160a01b031614156119615760405162461bcd60e51b815260040161033390612c07565b826001600160a01b0316846001600160a01b031610611981578284611984565b83835b90925090506001600160a01b0382166119af5760405162461bcd60e51b815260040161033390612f55565b9250929050565b60008383836040516020016119cc9291906127ad565b604051602081830303815290604052805190602001206040516020016119f39291906127d4565b60408051601f198184030181529190528051602090910120949350505050565b6000806000611a20612209565b9050836001600160a01b0316635909c0d56040518163ffffffff1660e01b815260040160206040518083038186803b158015611a5b57600080fd5b505afa158015611a6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a93919061274c565b9250836001600160a01b0316635a3d54936040518163ffffffff1660e01b815260040160206040518083038186803b158015611ace57600080fd5b505afa158015611ae2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b06919061274c565b91506000806000866001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b158015611b4657600080fd5b505afa158015611b5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b7e91906126f8565b925092509250826001600160701b0316600014158015611ba657506001600160701b03821615155b611bc25760405162461bcd60e51b815260040161033390612d3b565b8363ffffffff168163ffffffff1614611c1c5780840363ffffffff8116611be984866115eb565b516001600160e01b031602969096019563ffffffff8116611c0a85856115eb565b516001600160e01b0316029590950194505b5050509193909250565b6000806000611c3484611d92565b600082815260208890526040812054929450909250611c59828463ffffffff611da016565b159050801561042657611c72828463ffffffff61221316565b6000858152602089905260409020559695505050505050565b6060828203600080611c9c86611d92565b91509150600080611cac87611d92565b9150915084600202601e016001600160401b0381118015611ccc57600080fd5b506040519080825280601f01601f191660200182016040528015611cf7576020820181803683370190505b50600080825285815260208b905260408120549197508591611d1f908663ffffffff61221b16565b905060005b84831015611d6057611d3d89838363ffffffff61222416565b600192909201600081815260208d90526040902054909290915061010001611d24565b611d70828563ffffffff61237516565b9150611d8389838363ffffffff61222416565b50505050505050509392505050565b61010081049160ff90911690565b1c60019081161490565b600080611db5612209565b9050826001600160a01b0316635909c0d56040518163ffffffff1660e01b815260040160206040518083038186803b158015611df057600080fd5b505afa158015611e04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e28919061274c565b91506000806000856001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b158015611e6857600080fd5b505afa158015611e7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ea091906126f8565b925092509250826001600160701b0316600014158015611ec857506001600160701b03821615155b611ee45760405162461bcd60e51b815260040161033390612ccf565b8363ffffffff168163ffffffff1614611f1d5780840363ffffffff8116611f0b84866115eb565b516001600160e01b0316029590950194505b505050915091565b600080611f30612209565b9050826001600160a01b0316635a3d54936040518163ffffffff1660e01b815260040160206040518083038186803b158015611f6b57600080fd5b505afa158015611f7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fa3919061274c565b91506000806000856001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b158015611fe357600080fd5b505afa158015611ff7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201b91906126f8565b925092509250826001600160701b031660001415801561204357506001600160701b03821615155b61205f5760405162461bcd60e51b8152600401610333906129d9565b8363ffffffff168163ffffffff1614611f1d5780840363ffffffff8116611f0b85856115eb565b610e10900690565b60008060008061209d86611d92565b90925090506000808080846120d857856120c95760405162461bcd60e51b815260040161033390612f8c565b6001860395506001935061211e565b50600085815260208b905260409020546120f8818663ffffffff61238316565b9093509150821561210f578185038401935061211e565b60001990950194928401600101925b8215801561212c5750888411155b1561218d5750600085815260208b9052604090205480612170578561215e5750600096508695506116c3945050505050565b61010084019350600186039550612188565b612179816123be565b91508160ff0384019350600192505b61211e565b888411156121a85750600096508695506116c3945050505050565b60016121b48784612475565b97509750505050505050935093915050565b6121ce612480565b60405180602001604052808363ffffffff168686036001600160e01b0316816121f357fe5b046001600160e01b031681525090509392505050565b63ffffffff421690565b6001901b1790565b600019901b1690565b8161222e57612370565b82518060208501018060005b85811c1561236a575b85811c60ff1661225557600801612243565b85811c60071680801561229f57600181146122a457600281146122b757600381146122cd57600481146122ea5760058114612300576006811461231d576007811461233d57612360565b612360565b86830160f01b8452600284019350612360565b86600184010160f01b8452600284019350612360565b86600184010160e01b87840160f01b178452600484019350612360565b86600284010160f01b8452600284019350612360565b86600284010160e01b87840160f01b178452600484019350612360565b86600284010160e01b87600185010160f01b178452600484019350612360565b86600284010160d01b87600185010160e01b1787840160f01b1784526006840193505b505060030161223a565b50030183525b505050565b60001960ff919091031c1690565b60008061010083900384901b806123a15750600091508190506119af565b600184610100036123b1836123be565b0392509250509250929050565b600081806123de5760405162461bcd60e51b81526004016103339061298d565b600160801b81106123f1576080918201911c5b680100000000000000008110612409576040918201911c5b640100000000811061241d576020918201911c5b62010000811061242f576010918201911c5b6101008110612440576008918201911c5b60108110612450576004918201911c5b60048110612460576002918201911c5b6002811061246f576001820191505b50919050565b610100919091020190565b60408051602081019091526000815290565b604080518082019091526000808252602082015290565b604080516060810182526000808252602082018190529181019190915290565b6040518060200160405280600081525090565b80356001600160a01b038116811461030957600080fd5b60008083601f840112612504578182fd5b5081356001600160401b0381111561251a578182fd5b60208301915083602080830285010111156119af57600080fd5b600060208284031215612545578081fd5b61030683836124dc565b60008060408385031215612561578081fd5b61256b84846124dc565b946020939093013593505050565b60008060006060848603121561258d578081fd5b61259785856124dc565b95602085013595506040909401359392505050565b600080600080608085870312156125c1578081fd5b84356001600160a01b03811681146125d7578182fd5b966020860135965060408601359560600135945092505050565b60008060208385031215612603578182fd5b82356001600160401b03811115612618578283fd5b612624858286016124f3565b90969095509350505050565b60008060008060008060808789031215612648578182fd5b86356001600160401b038082111561265e578384fd5b61266a8a838b016124f3565b90985096506020890135915080821115612682578384fd5b5061268f89828a016124f3565b979a9699509760408101359660609091013595509350505050565b600080600080606085870312156126bf578384fd5b84356001600160401b038111156126d4578485fd5b6126e0878288016124f3565b90989097506020870135966040013595509350505050565b60008060006060848603121561270c578283fd5b835161271781613063565b602085015190935061272881613063565b604085015190925063ffffffff81168114612741578182fd5b809150509250925092565b60006020828403121561275d578081fd5b5051919050565b805163ffffffff1682526020808201516001600160e01b039081169184019190915260409182015116910152565b80516001600160e01b03908116835260209182015116910152565b6bffffffffffffffffffffffff19606093841b811682529190921b16601482015260280190565b6001600160f81b0319815260609290921b6bffffffffffffffffffffffff1916600183015260158201527f96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f603582015260550190565b6020808252825182820181905260009190848201906040850190845b81811015612864578351151583529284019291840191600101612846565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156128645761289f838551612764565b928401926060929092019160010161288c565b602080825282518282018190526000919060409081850190868401855b828110156128f2576128e2848351612792565b92840192908501906001016128cf565b5091979650505050505050565b6020808252825182820181905260009190848201906040850190845b81811015612864578351516001600160e01b03168352928401929184019160010161291b565b6020808252825182820181905260009190848201906040850190845b818110156128645783516001600160901b03168352928401929184019160010161295d565b901515815260200190565b6020808252602c908201527f426974733a3a686967686573744269745365743a2056616c756520302068617360408201526b081b9bc8189a5d1cc81cd95d60a21b606082015260800190565b60208082526046908201527f556e697377617056324f7261636c654c6962726172793a3a63757272656e744360408201527f756d756c61746976655072696365313a205061697220686173206e6f2072657360608201526532b93b32b99760d11b608082015260a00190565b6020808252604a908201527f496e6465786564556e697377617056324f7261636c653a3a5f67657454776f5760408201527f617950726963653a204e6f20707269636520666f756e6420696e2070726f76696060820152693232b2103930b733b29760b11b608082015260a00190565b60208082526050908201527f496e6465786564556e697377617056324f7261636c653a3a76616c69644d696e60408201527f4d61783a204d696e696d756d206167652063616e206e6f74206265206869676860608201526f32b9103a3430b71036b0bc34b6bab69760811b608082015260a00190565b60208082526049908201527f496e6465786564556e697377617056324f7261636c653a3a5f676574546f6b6560408201527f6e50726963653a204e6f20707269636520666f756e6420696e2070726f76696460608201526832b2103930b733b29760b91b608082015260a00190565b60208082526047908201527f496e6465786564556e697377617056324f7261636c653a3a5f6765744574685060408201527f726963653a204e6f20707269636520666f756e6420696e2070726f7669646564606082015266103930b733b29760c91b608082015260a00190565b60208082526025908201527f556e697377617056324c6962726172793a204944454e544943414c5f41444452604082015264455353455360d81b606082015260800190565b6020808252605e908201527f496e6465786564556e697377617056324f7261636c653a3a636f6d707574654160408201527f766572616765546f6b656e73466f724574683a20546f6b656e7320616e64206160608201527f6d6f756e7473206861766520646966666572656e74206c656e677468732e0000608082015260a00190565b60208082526046908201527f556e697377617056324f7261636c654c6962726172793a3a63757272656e744360408201527f756d756c61746976655072696365303a205061697220686173206e6f2072657360608201526532b93b32b99760d11b608082015260a00190565b60208082526046908201527f556e697377617056324f7261636c654c6962726172793a3a63757272656e744360408201527f756d756c61746976655072696365733a205061697220686173206e6f2072657360608201526532b93b32b99760d11b608082015260a00190565b60208082526047908201527f496e646578656450726963654d61704c6962726172793a3a676574507269636560408201527f4f62736572766174696f6e73496e52616e67653a20496e76616c69642074696d606082015266652072616e676560c81b608082015260a00190565b6020808252605e908201527f496e6465786564556e697377617056324f7261636c653a3a636f6d707574654160408201527f766572616765457468466f72546f6b656e733a20546f6b656e7320616e64206160608201527f6d6f756e7473206861766520646966666572656e74206c656e677468732e0000608082015260a00190565b60208082526023908201527f4669786564506f696e743a204d554c5449504c49434154494f4e5f4f564552466040820152624c4f5760e81b606082015260800190565b60208082526055908201527f496e6465786564556e697377617056324f7261636c653a3a676574507269636560408201527f4f62736572766174696f6e496e57696e646f773a204e6f207072696365206f6260608201527439b2b93b32b21034b71033b4bb32b7103437bab91760591b608082015260a00190565b6020808252601e908201527f556e697377617056324c6962726172793a205a45524f5f414444524553530000604082015260600190565b60208082526038908201527f4b6579496e6465783a3a66696e644c6173745365744b65793a43616e206e6f7460408201527f2071756572792076616c7565207072696f7220746f20302e0000000000000000606082015260800190565b60208082526017908201527f4669786564506f696e743a204449565f42595f5a45524f000000000000000000604082015260600190565b606081016103098284612764565b604081016103098284612792565b90516001600160e01b0316815260200190565b6001600160901b0391909116815260200190565b6001600160701b038116811461307857600080fd5b5056fea2646970667358221220a846e57523fbe71d04a80087a86961afe3195a7659fb3586d4c1945e4b0904c164736f6c634300060800330000000000000000000000005757371414417b8c6caad45baef941abc7d3ab320000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270

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

0000000000000000000000005757371414417b8c6caad45baef941abc7d3ab320000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270

-----Decoded View---------------
Arg [0] : uniswapFactory (address): 0x5757371414417b8c6caad45baef941abc7d3ab32
Arg [1] : weth (address): 0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000005757371414417b8c6caad45baef941abc7d3ab32
Arg [1] : 0000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270


Deployed ByteCode Sourcemap

356:19260:1:-:0;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;356:19260:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;3002:181:1;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;11370:486;;;;;;;;;:::i;:::-;;;;;;;;7138:324;;;;;;;;;:::i;:::-;;;;;;;;16152:737;;;;;;;;;:::i;:::-;;;;;;;;13546:422;;;;;;;;;:::i;:::-;;;;;;;;6219:324;;;;;;;;;:::i;:::-;;;;;;;;4520:235;;;;;;;;;:::i;9159:493::-;;;;;;;;;:::i;:::-;;;;;;;;14718:742;;;;;;;;;:::i;2436:289::-;;;;;;;;;:::i;:::-;;;;;;;;5039:428;;;;;;;;;:::i;8057:320::-;;;;;;;;;:::i;1810:304::-;;;;;;;;;:::i;12512:429::-;;;;;;;;;:::i;3436:392::-;;;;;;;;;:::i;:::-;;;;;;;;10266:490;;;;;;;;;:::i;3939:271::-;;;;;;;;;:::i;:::-;;;;;;;;3002:181;-1:-1:-1;;;;;3129:22:1;;3108:4;3129:22;;;;;;;;;;:49;;3169:8;3129:49;:39;:49;:::i;:::-;3122:56;;3002:181;;;;;:::o;11370:486::-;11590:43;11545:14;11561;1187;1169;:32;;1154:143;;;;-1:-1:-1;;;1154:143:1;;;;;;;;;;;;;;;;;11657:6;;-1:-1:-1;;;;;11692:31:1;::::1;2:2:-1::0;::::1;;;27:1;24::::0;17:12:::1;2:2;11692:31:1;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1::0;11676:47:1;-1:-1:-1;11734:9:1::1;11729:123;11753:3;11749:1;:7;11729:123;;;11790:55;11803:6;;11810:1;11803:9;;;;;;;;;;;;;;;;;;;;;;11814:14;11830;11790:12;:55::i;:::-;11771:13;11785:1;11771:16;;;;;;;;;::::0;;::::1;::::0;;;;;:74;11758:3:::1;;11729:123;;;;1303:1;11370:486:::0;;;;;;;;:::o;7138:324::-;7347:40;;:::i;:::-;7302:14;7318;1187;1169;:32;;1154:143;;;;-1:-1:-1;;;1154:143:1;;;;;;;;;7404:53:::1;7419:5;7426:14;7442;7404;:53::i;:::-;7397:60:::0;7138:324;-1:-1:-1;;;;;;7138:324:1:o;16152:737::-;16411:36;16366:14;16382;1187;1169;:32;;1154:143;;;;-1:-1:-1;;;1154:143:1;;;;;;;;;16471:6;16505:25;;::::1;16490:150;;;;-1:-1:-1::0;;;16490:150:1::1;;;;;;;;;16682:3;-1:-1:-1::0;;;;;16668:18:1::1;;5:9:-1;2:2;;;27:1;24::::0;17:12:::1;2:2;16668:18:1;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;::::0;-1:-1;16668:18:1::1;-1:-1:-1::0;16646:40:1;-1:-1:-1;16697:9:1::1;16692:193;16716:3;16712:1;:7;16692:193;;;16759:119;:107;16851:11;;16863:1;16851:14;;;;;;;;;;;;;16759:87;16781:6;;16788:1;16781:9;;;;;;;;;;;;;;;;;;;;;;16800:14;16824;16759:12;:87::i;:::-;:91:::0;:107:::1;:91;:107;:::i;:::-;:117;:119::i;:::-;16734:19;16754:1;16734:22;;;;;;;;-1:-1:-1::0;;;;;16734:144:1;;::::1;:22;::::0;;::::1;::::0;;;;;;;:144;16721:3:::1;;16692:193;;;;1303:1;16152:737:::0;;;;;;;;;;:::o;13546:422::-;13781:7;13736:14;13752;1187;1169;:32;;1154:143;;;;-1:-1:-1;;;1154:143:1;;;;;;;;;13824:36:::1;;:::i;:::-;13863:51;13876:5;13883:14;13899;13863:12;:51::i;:::-;13824:90:::0;-1:-1:-1;13927:36:1::1;:24;13824:90:::0;13940:10;13927:24:::1;:12;:24;:::i;:36::-;13920:43:::0;13546:422;-1:-1:-1;;;;;;;;13546:422:1:o;6219:324::-;6429:38;;:::i;:::-;6384:14;6400;1187;1169;:32;;1154:143;;;;-1:-1:-1;;;1154:143:1;;;;;;;;;6484:54:::1;6500:5;6507:14;6523;6484:15;:54::i;4520:235::-:0;4591:4;4628:45;-1:-1:-1;;;;;4628:15:1;:31;4660:5;4667;4628:45;:31;:45;:::i;:::-;4623:64;;-1:-1:-1;4682:5:1;4675:12;;4623:64;-1:-1:-1;;;;;4700:22:1;;:15;:22;;;;;;;;;;:50;;4745:3;4700:50;:37;:50;:::i;:::-;4693:57;;4520:235;;;;:::o;9159:493::-;9382:47;9337:14;9353;1187;1169;:32;;1154:143;;;;-1:-1:-1;;;1154:143:1;;;;;;;;;9453:6;;-1:-1:-1;;;;;9481:42:1;::::1;2:2:-1::0;::::1;;;27:1;24::::0;17:12:::1;2:2;9481:42:1;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1::0;9472:51:1;-1:-1:-1;9534:9:1::1;9529:119;9553:3;9549:1;:7;9529:119;;;9583:58;9599:6;;9606:1;9599:9;;;;;;;;;;;;;;;;;;;;;;9610:14;9626;9583:15;:58::i;:::-;9571:6;9578:1;9571:9;;;;;;;;;::::0;;::::1;::::0;;;;;:70;9558:3:::1;;9529:119;;14718:742:::0;14978:36;14933:14;14949;1187;1169;:32;;1154:143;;;;-1:-1:-1;;;1154:143:1;;;;;;;;;15038:6;15072:26;;::::1;15057:151;;;;-1:-1:-1::0;;;15057:151:1::1;;;;;;;;;15250:3;-1:-1:-1::0;;;;;15236:18:1::1;;5:9:-1;2:2;;;27:1;24::::0;17:12:::1;2:2;15236:18:1;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;::::0;-1:-1;15236:18:1::1;-1:-1:-1::0;15214:40:1;-1:-1:-1;15265:9:1::1;15260:196;15284:3;15280:1;:7;15260:196;;;15327:122;:110;15421:12;;15434:1;15421:15;;;;;;;;;;;;;15327:89;15351:6;;15358:1;15351:9;;;;;;;;;;;;;;;;;;;;;;15370:14;15394;15327;:89::i;:122::-;15302:19;15322:1;15302:22;;;;;;;;-1:-1:-1::0;;;;;15302:147:1;;::::1;:22;::::0;;::::1;::::0;;;;;;;:147;15289:3:::1;;15260:196;;2436:289:::0;2524:27;2575:6;;-1:-1:-1;;;;;2610:15:1;;2:2:-1;;;;27:1;24;17:12;2:2;2610:15:1;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;;-1:-1;2610:15:1;-1:-1:-1;2594:31:1;-1:-1:-1;2636:9:1;2631:90;2655:3;2651:1;:7;2631:90;;;2692:22;2704:6;;2711:1;2704:9;;;;;;;;;;;;;;;;;;;;;2692:22;2673:13;2687:1;2673:16;;;;;;;;:41;;;:16;;;;;;;;;;;:41;2660:3;;2631:90;;;;2436:289;;;;;:::o;5039:428::-;5123:26;5171:6;;-1:-1:-1;;;;;5205:15:1;;2:2:-1;;;;27:1;24;17:12;2:2;5205:15:1;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;;-1:-1;5205:15:1;-1:-1:-1;5190:30:1;-1:-1:-1;5231:9:1;5226:237;5250:3;5246:1;:7;5226:237;;;5268:13;5284:6;;5291:1;5284:9;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;5320:22:1;;5301:16;5320:22;;;;;;;;;;5268:25;;-1:-1:-1;5301:16:1;5320:50;;5365:3;5320:50;:37;:50;:::i;:::-;5301:69;;5396:11;:60;;;;-1:-1:-1;5411:45:1;-1:-1:-1;;;;;5411:15:1;:31;5443:5;5450;5411:45;:31;:45;:::i;:::-;5378:12;5391:1;5378:15;;;;;;;;:78;;;:15;;;;;;;;;;;:78;-1:-1:-1;;5255:3:1;;5226:237;;8057:320;8264:40;;:::i;:::-;8219:14;8235;1187;1169;:32;;1154:143;;;;-1:-1:-1;;;1154:143:1;;;;;;;;;8321:51:::1;8334:5;8341:14;8357;8321:12;:51::i;1810:304::-:0;1871:4;1916:5;-1:-1:-1;;;;;1907:14:1;:5;-1:-1:-1;;;;;1907:14:1;;1903:31;;;-1:-1:-1;1930:4:1;1923:11;;1903:31;1940:48;;:::i;:::-;1991;-1:-1:-1;;;;;1991:15:1;:34;2026:5;2033;1991:48;:34;:48;:::i;:::-;-1:-1:-1;;;;;2052:22:1;;:15;:22;;;;;;;;;;1940:99;;-1:-1:-1;2052:57:1;;1940:99;2052:57;:44;:57;:::i;:::-;2045:64;1810:304;-1:-1:-1;;;1810:304:1:o;12512:429::-;12748:7;12703:14;12719;1187;1169;:32;;1154:143;;;;-1:-1:-1;;;1154:143:1;;;;;;;;;12790:38:::1;;:::i;:::-;12831:53;12846:5;12853:14;12869;12831;:53::i;3436:392::-:0;3554:48;;:::i;:::-;-1:-1:-1;;;;;3626:22:1;;:15;:22;;;;;;;;;;:49;;3666:8;3626:49;:39;:49;:::i;:::-;3696:21;;3612:63;;-1:-1:-1;3696:26:1;;3681:142;;;;-1:-1:-1;;;3681:142:1;;;;;;;;10266:490;10488:43;10443:14;10459;1187;1169;:32;;1154:143;;;;-1:-1:-1;;;1154:143:1;;;;;;;;;10555:6;;-1:-1:-1;;;;;10590:31:1;::::1;2:2:-1::0;::::1;;;27:1;24::::0;17:12:::1;2:2;10590:31:1;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1::0;10574:47:1;-1:-1:-1;10632:9:1::1;10627:125;10651:3;10647:1;:7;10627:125;;;10688:57;10703:6;;10710:1;10703:9;;;;;;;;;;;;;;;;;;;;;;10714:14;10730;10688;:57::i;:::-;10669:13;10683:1;10669:16;;;;;;;;;::::0;;::::1;::::0;;;;;:76;10656:3:::1;;10627:125;;3939:271:::0;-1:-1:-1;;;;;4137:22:1;;:15;:22;;;;;;;;;;4073:45;;4137:68;;4188:8;4198:6;4137:68;:50;:68;:::i;:::-;4128:77;3939:271;-1:-1:-1;;;;3939:271:1:o;4266:185:5:-;4386:4;4405:41;:15;4437:8;4405:41;:31;:41;:::i;18753:861:1:-;18889:27;;:::i;:::-;18939:5;-1:-1:-1;;;;;18930:14:1;:5;-1:-1:-1;;;;;18930:14:1;;18926:67;;;18961:25;18981:1;18984;18961:19;:25::i;:::-;18954:32;;;;18926:67;18999:16;;19047:42;-1:-1:-1;;;;;19047:15:1;:28;19076:5;19083;19047:42;:28;:42;:::i;:::-;-1:-1:-1;;;;;19137:22:1;;19096:15;19137:22;;;;;;;;;;18998:91;;-1:-1:-1;18998:91:1;;-1:-1:-1;19096:15:1;;;19137:113;;;;;;;19208:14;;19230;;19137:46;:113;:::i;:::-;19095:155;;;;19264:10;19256:94;;;;-1:-1:-1;;;19256:94:1;;;;;;;;;-1:-1:-1;;;;;19405:22:1;;19356:46;19405:22;;;;;;;;;;;:45;;;:31;;;;:45;;;;;;19503:18;;19529:31;;;;19405:45;;19463:146;;19503:18;;;;;-1:-1:-1;;;;;19529:31:1;19568:9;19585:18;19463:32;:146::i;:::-;19456:153;18753:861;-1:-1:-1;;;;;;;;;18753:861:1:o;17887:862::-;18025:27;;:::i;:::-;18075:5;-1:-1:-1;;;;;18066:14:1;:5;-1:-1:-1;;;;;18066:14:1;;18062:67;;;18097:25;18117:1;18120;18097:19;:25::i;18062:67::-;18135:16;;18183:42;-1:-1:-1;;;;;18183:15:1;:28;18212:5;18219;18183:42;:28;:42;:::i;:::-;-1:-1:-1;;;;;18273:22:1;;18232:15;18273:22;;;;;;;;;;18134:91;;-1:-1:-1;18134:91:1;;-1:-1:-1;18232:15:1;;;18273:113;;;;;;;18344:14;;18366;;18273:46;:113;:::i;:::-;18231:155;;;;18400:10;18392:96;;;;-1:-1:-1;;;18392:96:1;;;;;;;;;-1:-1:-1;;;;;18543:22:1;;18494:46;18543:22;;;;;;;;;;;:45;;;:31;;:45;;;;;18641:18;;18601:143;;18641:18;;;;18667:28;;;-1:-1:-1;;;;;18667:28:1;18703:9;18720:18;18601:32;:143::i;1647:253:4:-;1714:16;;:::i;:::-;1738:6;1765;;;:54;;-1:-1:-1;;1811:7:4;;-1:-1:-1;;;;;1806:13:4;1780:17;;;;1801:1;1780:17;1801:1;1775:27;;;;;:44;1765:54;1750:120;;;;-1:-1:-1;;;1750:120:4;;;;;;;;;1883:12;;;;;;;;;;;;;1647:253;-1:-1:-1;;;1647:253:4:o;2556:122::-;2651:7;873:3;2651:21;;2556:122::o;16942:941:1:-;17081:38;;:::i;:::-;17142:5;-1:-1:-1;;;;;17133:14:1;:5;-1:-1:-1;;;;;17133:14:1;;17129:147;;;17164:105;;;;;;;;17205:20;17223:1;17205:17;:20::i;:::-;:23;-1:-1:-1;;;;;17164:105:1;;;;;17238:20;17256:1;17238:17;:20::i;:::-;:23;-1:-1:-1;;;;;17164:105:1;;;17157:112;-1:-1:-1;17157:112:1;;17129:147;17321:44;;:::i;:::-;17368:48;-1:-1:-1;;;;;17368:15:1;:34;17403:5;17410;17368:48;:34;:48;:::i;:::-;17553:17;;-1:-1:-1;;;;;17499:22:1;;17458:15;17499:22;;;;;;;;;;17321:95;;-1:-1:-1;17458:15:1;;;17499:121;;:22;:121;;;;;17578:14;;17600;;17499:46;:121;:::i;:::-;17457:163;;;;17634:10;17626:97;;;;-1:-1:-1;;;17626:97:1;;;;;;;;;17729:45;;:::i;:::-;-1:-1:-1;;;;;;17777:22:1;;:15;:22;;;;;;;;;;;:45;;;:31;;;;:45;;;;;;17729:93;;;;;;;;;;;;;;;-1:-1:-1;;;;;17729:93:1;;;;;;;;;;;;;;;;;;;;;;;17835:43;;17729:93;;17870:7;;17835:34;:43;:::i;900:339:7:-;1029:4;1043:12;1058:53;1083:14;1099:5;1106:4;1058:24;:53::i;:::-;1043:68;;1118:16;1136;1172:4;-1:-1:-1;;;;;1157:32:7;;:34;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1157:34:7;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1157:34:7;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;1157:34:7;;;;;;;;;1117:74;;;;;1204:8;-1:-1:-1;;;;;1204:13:7;1216:1;1204:13;;:30;;;;-1:-1:-1;;;;;;1221:13:7;;;;1204:30;1197:37;900:339;-1:-1:-1;;;;;;;900:339:7:o;3710:414:5:-;3831:4;3863:16;3882:24;3893:12;3882:24;;:10;:24::i;:::-;3863:43;-1:-1:-1;3991:41:5;:15;3863:43;3991:41;:31;:41;:::i;:::-;3987:59;;;4041:5;4034:12;;;;;3987:59;4059:60;4089:15;4106:12;4059:29;:60::i;2161:1035:7:-;2281:23;;:::i;:::-;2313:14;2329;2347:40;2375:5;2382:4;2347:27;:40::i;:::-;2312:75;;;;2393:12;2408:62;2439:14;2455:6;2463;2408:30;:62::i;:::-;2393:77;;2519:24;2551;2583:21;2613:52;2660:4;2613:46;:52::i;:::-;2511:154;;;;;;2783:5;-1:-1:-1;;;;;2773:15:7;:6;-1:-1:-1;;;;;2773:15:7;;2769:423;;;2805:176;;;;;;;;2843:14;2805:176;;;;;;2896:16;-1:-1:-1;;;;;2805:176:7;;;;;2955:16;-1:-1:-1;;;;;2805:176:7;;;;2798:183;;;;;;;;;;2769:423;3009:176;;;;;;;;3047:14;3009:176;;;;;;3100:16;-1:-1:-1;;;;;3009:176:7;;;;;3159:16;-1:-1:-1;;;;;3009:176:7;;;;3002:183;;;;;;;;;;2769:423;2161:1035;;;;;;;;;;;:::o;1750:538:5:-;1902:4;1934:14;1951:69;1981:15;1998:11;:21;;;1951:29;:69::i;:::-;1934:86;;2030:9;2026:236;;;2049:16;2068:33;2079:11;:21;;;2068:33;;:10;:33::i;:::-;2049:52;-1:-1:-1;2121:45:5;:15;2049:52;2121:45;:35;:45;:::i;:::-;2109:57;;2178:9;2174:82;;;2199:34;;;;:24;;;;:34;;;;;;;;;:48;;;;;;;;-1:-1:-1;;2199:48:5;;;;;;;;;;-1:-1:-1;;;;;2199:48:5;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;2199:48:5;;;;;;;;;;;2174:82;2026:236;2274:9;1750:538;-1:-1:-1;;;1750:538:5:o;4522:210::-;4642:36;;:::i;:::-;-1:-1:-1;4693:34:5;;;;:24;;;;:34;;;;;;;;;4686:41;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;4686:41:5;;;;;;;;;;;;;;;;;;;4522:210::o;4736:1057::-;4899:45;4954:20;4977;4988:8;4977:10;:20::i;:::-;4954:43;;5003:18;5024;5035:6;5024:10;:18::i;:::-;5003:39;;5069:12;5056:10;:25;5048:109;;;;-1:-1:-1;;;5048:109:5;;;;;;;;;5163:25;5191:75;:15;5241:12;5255:10;5191:75;:49;:75;:::i;:::-;5163:103;;5360:11;5396:1;5374:12;:19;:23;;;;;;5360:37;;5448:3;-1:-1:-1;;;;;5412:40:5;;5:9:-1;2:2;;;27:1;24;17:12;2:2;5412:40:5;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;5403:49:5;-1:-1:-1;5511:2:5;5493:21;;5458:11;5521:268;5545:3;5541:1;:7;5521:268;;;5638:10;;5632:4;5628:21;5705:28;;;5563:21;5753:29;;;:24;;;;:29;;;;;;;;;5741:41;;;;;;;;;;;;;;-1:-1:-1;;;;;5741:41:5;;;;;;;;;;;;;;;;;;;;;;;;:9;;5674:1;5665:11;;;;5741:6;;5748:1;;5741:9;;;;;;;;;;;;;;;:41;-1:-1:-1;;5550:3:5;;5521:268;;2563:330:6;2676:4;2689:16;2707:21;2732:27;2752:6;2732:19;:27::i;:::-;2765:18;2786;;;;;;;;;;;2688:71;;-1:-1:-1;2688:71:6;-1:-1:-1;2814:15:6;2810:33;;2838:5;2831:12;;;;;;;2810:33;2856:32;:10;2874:13;2856:32;:17;:32;:::i;2046:233:4:-;2127:16;;:::i;:::-;2173:1;2159:11;-1:-1:-1;;;;;2159:15:4;;2151:51;;;;-1:-1:-1;;;2151:51:4;;;;;;;;;2215:59;;;;;;;;;;-1:-1:-1;;;;;2225:48:4;;-1:-1:-1;;;;;;;873:3:4;2226:32;;;;2225:48;;;;;;-1:-1:-1;;;;;2215:59:4;;;;2208:66;;2046:233;;;;:::o;1243:760:7:-;1377:6;1401:7;1445:14;1461;1479:48;1507:7;1516:10;1479:27;:48::i;:::-;1444:83;;;;1533:12;1548:62;1579:14;1595:6;1603;1548:30;:62::i;:::-;1533:77;;1630:7;-1:-1:-1;;;;;1620:17:7;:6;-1:-1:-1;;;;;1620:17:7;;1616:383;;;1648:24;1674:21;1699:52;1746:4;1699:46;:52::i;:::-;1647:104;-1:-1:-1;1647:104:7;-1:-1:-1;1759:50:7;;-1:-1:-1;;;;;1759:50:7;1616:383;1831:24;1857:21;1882:52;1929:4;1882:46;:52::i;1243:760::-;;;;;;;:::o;6518:1554:5:-;6714:4;6737:7;6773:16;6792:21;6803:9;6792:10;:21::i;:::-;6773:40;;6819:25;6847:38;6875:9;6847:27;:38::i;:::-;6819:66;-1:-1:-1;6914:35:5;;;;6979;;;;6914;;7350;;;7369:16;7350:35;7346:490;;;7395:49;7447:34;;;:24;;;:34;;;;;7511:21;;;;7553:17;;;;;:53;;;7594:12;7582:24;;:9;:24;7553:53;:107;;;;;7646:14;7630:12;7618:24;;:9;:24;:42;;7553:107;:161;;;;;7700:14;7684:12;7672:24;;:9;:24;:42;;7553:161;7540:225;;;7741:4;7747:8;7733:23;;;;;;;;;;;;7540:225;7776:16;7772:58;;;-1:-1:-1;7812:5:5;;-1:-1:-1;7812:5:5;;-1:-1:-1;7804:17:5;;-1:-1:-1;;;;;7804:17:5;7772:58;7346:490;;;7868:26;;;7911:27;7868:26;7911:10;:27::i;:::-;7900:38;;7944:19;7966:26;7977:14;7966:10;:26::i;:::-;7944:48;-1:-1:-1;8005:62:5;:15;8045:8;7944:48;8005:62;:39;:62;:::i;:::-;7998:69;;;;;;;;;;6518:1554;;;;;;;;:::o;4196:368:7:-;4370:27;;:::i;:::-;4412:147;4462:20;4490:18;4538:14;4523:12;:29;4412:42;:147::i;:::-;4405:154;4196:368;-1:-1:-1;;;;;4196:368:7:o;1023:121:4:-;1073:16;;:::i;:::-;-1:-1:-1;1104:35:4;;;;;;;;;873:3;1114:24;;;;-1:-1:-1;;;;;;;1114:24:4;1104:35;;;1023:121::o;3412:780:7:-;3558:25;;:::i;:::-;3644:22;;3619;;:47;3673:40;;:::i;:::-;3716:147;3766:12;:32;;;3806:12;:32;;;3846:11;3716:42;:147::i;:::-;3673:190;;3869:43;;:::i;:::-;3915:153;3965:12;:35;;;4008:12;:35;;;4051:11;3915:42;:153::i;:::-;4081:106;;;;;;;;;4122:15;;-1:-1:-1;;;;;4081:106:7;;;;;4162:18;;4081:106;;;;;-1:-1:-1;4081:106:7;3412:780;-1:-1:-1;;;;3412:780:7:o;1574:242:8:-;1679:12;1700:14;1716;1734:26;1745:6;1753;1734:10;:26::i;:::-;1699:61;;;;1773:38;1787:7;1796:6;1804;1773:13;:38::i;906:133:5:-;461:7;1004:30;;;906:133::o;2559:901::-;2695:4;2731:16;2750:24;2761:12;2750:24;;:10;:24::i;:::-;2731:43;;585:9;2952:41;2980:12;2952:41;;:27;:41::i;:::-;:70;2948:490;;3039:4;3032:11;;;;;2948:490;-1:-1:-1;;3248:12:5;;3167:53;3223:38;;;:24;;;:38;;;;;3282:25;;;;:30;;:111;;-1:-1:-1;3339:25:5;;585:9;3339:25;;;;3324:40;;:69;;;;;3282:111;3269:163;;;3419:4;3412:11;;;;;;3269:163;-1:-1:-1;3450:5:5;;2559:901;-1:-1:-1;;;;2559:901:5:o;692:345:8:-;779:14;795;837:6;-1:-1:-1;;;;;827:16:8;:6;-1:-1:-1;;;;;827:16:8;;;819:66;;;;-1:-1:-1;;;819:66:8;;;;;;;;;919:6;-1:-1:-1;;;;;910:15:8;:6;-1:-1:-1;;;;;910:15:8;;:53;;948:6;956;910:53;;;929:6;937;910:53;891:72;;-1:-1:-1;891:72:8;-1:-1:-1;;;;;;977:20:8;;969:63;;;;-1:-1:-1;;;969:63:8;;;;;;;;;692:345;;;;;:::o;1041:448::-;1152:12;1283:7;1331:6;1339;1314:32;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;1314:32:8;;;1304:43;;;;;;1232:228;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;1232:228:8;;;1211:259;;49:4:-1;1211:259:8;;;;;1041:448;-1:-1:-1;;;;1041:448:8:o;1244:1217:9:-;1333:24;1365;1397:21;1450:23;:21;:23::i;:::-;1433:40;;1513:4;-1:-1:-1;;;;;1498:41:9;;:43;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1498:43:9;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1498:43:9;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;1498:43:9;;;;;;;;;1479:62;;1581:4;-1:-1:-1;;;;;1566:41:9;;:43;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1566:43:9;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1566:43:9;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;1566:43:9;;;;;;;;;1547:62;;1720:16;1744;1768:25;1817:4;-1:-1:-1;;;;;1802:32:9;;:34;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1802:34:9;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1802:34:9;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;1802:34:9;;;;;;;;;1712:124;;;;;;1857:8;-1:-1:-1;;;;;1857:13:9;1869:1;1857:13;;:30;;;;-1:-1:-1;;;;;;1874:13:9;;;;1857:30;1842:131;;;;-1:-1:-1;;;1842:131:9;;;;;;;;;2005:14;1983:36;;:18;:36;;;1979:478;;2091:35;;;2226:73;;;2234:39;2254:8;2264;2234:19;:39::i;:::-;:42;-1:-1:-1;;;;;2226:51:9;:73;2196:111;;;;;2369:73;;;2377:39;2397:8;2407;2377:19;:39::i;:::-;:42;-1:-1:-1;;;;;2369:51:9;:73;2339:111;;;;;-1:-1:-1;1979:478:9;1244:1217;;;;;;;;:::o;1939:470:6:-;2051:4;2080:16;2098:21;2123:27;2143:6;2123:19;:27::i;:::-;2199:18;2220;;;;;;;;;;;2079:71;;-1:-1:-1;2079:71:6;;-1:-1:-1;2262:32:6;2220:18;2079:71;2262:32;:17;:32;:::i;:::-;2261:33;2244:50;;2304:9;2300:83;;;2344:32;:10;2362:13;2344:32;:17;:32;:::i;:::-;2323:18;;;;;;;;;;;:53;2395:9;1939:470;-1:-1:-1;;;;;;1939:470:6:o;3061:1572::-;3218:25;3271:21;;;3251:17;;3352:31;3282:10;3352:19;:31::i;:::-;3298:85;;;;3390:19;3411:24;3439:29;3459:8;3439:19;:29::i;:::-;3389:79;;;;3769:9;3765:1;:13;3782:2;3764:20;-1:-1:-1;;;;;3754:31:6;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3754:31:6;;;;;;;;;;;;;;;;;;;;;;;;;;21:6:-1;;108:14;3754:31:6;87:42:-1;143:17;;-1:-1;3754:31:6;-1:-1:-1;3890:1:6;3869:23;;;4054:18;;;;;;;;;;;3739:46;;-1:-1:-1;3918:13:6;;4054:54;;4089:18;4054:54;:34;:54;:::i;:::-;4033:75;-1:-1:-1;4114:13:6;4191:248;4209:11;4198:8;:22;4191:248;;;4306:45;:12;4332:10;4344:6;4306:45;:25;:45;:::i;:::-;4371:1;4359:13;;;;4393:18;;;;;;;;;;;;4359:13;;4393:18;;-1:-1:-1;4429:3:6;4419:13;4191:248;;;4534:43;:10;4560:16;4534:43;:25;:43;:::i;:::-;4521:56;-1:-1:-1;4583:45:6;:12;4521:56;4621:6;4583:45;:25;:45;:::i;:::-;3061:1572;;;;;;;;;;;;;:::o;1437:191::-;1586:3;1577:12;;;1611;;;;;1437:191::o;503:116:3:-;591:13;608:1;590:19;;;:24;;503:116::o;2591:956:9:-;2673:24;2699:21;2747:23;:21;:23::i;:::-;2730:40;;2810:4;-1:-1:-1;;;;;2795:41:9;;:43;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2795:43:9;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;2795:43:9;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;2795:43:9;;;;;;;;;2776:62;;2949:16;2973;2997:25;3046:4;-1:-1:-1;;;;;3031:32:9;;:34;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3031:34:9;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;3031:34:9;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;3031:34:9;;;;;;;;;2941:124;;;;;;3086:8;-1:-1:-1;;;;;3086:13:9;3098:1;3086:13;;:30;;;;-1:-1:-1;;;;;;3103:13:9;;;;3086:30;3071:131;;;;-1:-1:-1;;;3071:131:9;;;;;;;;;3234:14;3212:36;;:18;:36;;;3208:335;;3320:35;;;3455:73;;;3463:39;3483:8;3493;3463:19;:39::i;:::-;:42;-1:-1:-1;;;;;3455:51:9;:73;3425:111;;;;;-1:-1:-1;3208:335:9;2591:956;;;;;;:::o;3678:::-;3760:24;3786:21;3834:23;:21;:23::i;:::-;3817:40;;3897:4;-1:-1:-1;;;;;3882:41:9;;:43;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3882:43:9;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;3882:43:9;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;3882:43:9;;;;;;;;;3863:62;;4036:16;4060;4084:25;4133:4;-1:-1:-1;;;;;4118:32:9;;:34;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;4118:34:9;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;4118:34:9;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;4118:34:9;;;;;;;;;4028:124;;;;;;4173:8;-1:-1:-1;;;;;4173:13:9;4185:1;4173:13;;:30;;;;-1:-1:-1;;;;;;4190:13:9;;;;4173:30;4158:131;;;;-1:-1:-1;;;4158:131:9;;;;;;;;;4321:14;4299:36;;:18;:36;;;4295:335;;4407:35;;;4542:73;;;4550:39;4570:8;4580;4550:19;:39::i;1145:153:5:-;461:7;1263:30;;;1145:153::o;5027:1328:6:-;5185:4;5202:7;5232:16;5250:21;5275:27;5295:6;5275:19;:27::i;:::-;5231:71;;-1:-1:-1;5231:71:6;-1:-1:-1;5308:16:6;;;;5462:18;5458:434;;5498:13;5490:82;;;;-1:-1:-1;;;5490:82:6;;;;;;;;;5592:1;5580:13;;;;5612:1;5601:12;;5458:434;;;-1:-1:-1;5647:18:6;;;;;;;;;;;;5693:42;5647:18;5721:13;5693:42;:27;:42;:::i;:::-;5673:62;;-1:-1:-1;5673:62:6;-1:-1:-1;5743:143:6;;;;5792:8;5776:13;:24;5764:36;;;;5743:143;;;-1:-1:-1;;5864:13:6;;;;5825:29;;;5853:1;5825:29;;5743:143;5906:5;5905:6;:33;;;;;5927:11;5915:8;:23;;5905:33;5898:339;;;-1:-1:-1;5961:18:6;;;;;;;;;;;;5991:15;5987:244;;6022:13;6018:36;;-1:-1:-1;6045:5:6;;-1:-1:-1;6045:5:6;;-1:-1:-1;6037:17:6;;-1:-1:-1;;;;;6037:17:6;6018:36;6076:3;6064:15;;;;6101:1;6089:13;;;;5987:244;;;6138:26;:10;:24;:26::i;:::-;6127:37;;6192:8;6186:3;:14;6174:26;;;;6218:4;6210:12;;5987:244;5898:339;;;6257:11;6246:8;:22;6242:60;;;-1:-1:-1;6286:5:6;;-1:-1:-1;6286:5:6;;-1:-1:-1;6278:17:6;;-1:-1:-1;;;;;6278:17:6;6242:60;6315:4;6321:28;6330:8;6340;6321;:28::i;:::-;6307:43;;;;;;;;;;5027:1328;;;;;;:::o;4638:342:9:-;4784:40;;:::i;:::-;4875:100;;;;;;;;4957:11;4911:57;;4933:20;4912:18;:41;-1:-1:-1;;;;;4911:57:9;;;;;;;-1:-1:-1;;;;;4875:100:9;;;;4860:115;;4638:342;;;;;:::o;1031:113::-;1115:23;:15;:23;;1031:113::o;277:116:3:-;115:1;375:12;;367:21;;277:116::o;904:128::-;-1:-1:-1;;1011:15:3;;1003:24;;904:128::o;2026:3704::-;2127:8;2123:21;;2137:7;;2123:21;2254:12;2248:19;2472:3;2467:2;2453:12;2449:21;2445:31;2580:8;2794:1;2780:2763;2800:11;;;2797:18;2780:2763;;2895:55;2909:11;;;2922:3;2905:21;2895:55;;2944:1;2937:9;2895:55;;;3010:11;;;3023:1;3006:19;;3148:9;;;;3187:1;3182:191;;;;3389:1;3384:199;;;;3599:1;3594:404;;;;4014:1;4009:199;;;;4224:1;4219:400;;;;4635:1;4630:399;;;;5045:1;5040:495;;;;3129:2406;;3148:9;;;3182:191;3321:6;3318:1;3314:14;3308:4;3304:25;3299:3;3292:38;3359:1;3354:3;3350:11;3343:18;;3182:191;;3384:199;3531:6;3527:1;3524;3520:9;3516:22;3510:4;3506:33;3501:3;3494:46;3569:1;3564:3;3560:11;3553:18;;3384:199;;3594:404;3917:6;3913:1;3910;3906:9;3902:22;3896:4;3892:33;3866:6;3863:1;3859:14;3853:4;3849:25;3788:153;3769:3;3747:208;3984:1;3979:3;3975:11;3968:18;;3594:404;;4009:199;4156:6;4152:1;4149;4145:9;4141:22;4135:4;4131:33;4126:3;4119:46;4194:1;4189:3;4185:11;4178:18;;4009:199;;4219:400;4510:6;4506:1;4503;4499:9;4495:22;4489:4;4485:33;4459:6;4456:1;4452:14;4446:4;4442:25;4381:153;4362:3;4340:208;4578:1;4573:3;4569:11;4562:18;;4219:400;;4630:399;4921:6;4917:1;4914;4910:9;4906:22;4900:4;4896:33;4870:6;4866:1;4863;4859:9;4855:22;4849:4;4845:33;4784:161;4765:3;4743:216;4988:1;4983:3;4979:11;4972:18;;4630:399;;5040:495;5409:6;5405:1;5402;5398:9;5394:22;5388:4;5384:33;5356:6;5352:1;5349;5345:9;5341:22;5335:4;5331:33;5309:126;5283:6;5280:1;5276:14;5270:4;5266:25;5205:246;5186:3;5164:301;5494:1;5489:3;5485:11;5478:18;;3129:2406;-1:-1:-1;;2829:1:3;2822:9;2780:2763;;;-1:-1:-1;5630:18:3;5703:16;5682:38;;2159:3567;;;;:::o;698:133::-;-1:-1:-1;;813:3:3;:11;;;;804:21;796:30;;698:133::o;7839:283::-;7927:20;;8001:3;:9;;;7992:19;;;8021:8;8017:46;;-1:-1:-1;8047:5:3;;-1:-1:-1;8047:5:3;;-1:-1:-1;8039:17:3;;8017:46;8076:4;8111:3;8105;:9;8083:18;8097:3;8083:13;:18::i;:::-;:32;8068:49;;;;;7839:283;;;;;:::o;5845:555::-;5905:9;5934:4;5953:5;5944:63;;;;-1:-1:-1;;;5944:63:3;;;;;;;;;-1:-1:-1;;;6017:1:3;:40;6013:68;;6066:3;6071:8;;;;6060:9;6013:68;6095:19;6090:1;:24;6086:50;;6123:2;6127:7;;;;6117:8;6086:50;6150:11;6145:1;:16;6141:42;;6170:2;6174:7;;;;6164:8;6141:42;6197:7;6192:1;:12;6188:38;;6213:2;6217:7;;;;6207:8;6188:38;6240:5;6235:1;:10;6231:34;;6254:1;6257:6;;;;6248:7;6231:34;6279:4;6274:1;:9;6270:33;;6292:1;6295:6;;;;6286:7;6270:33;6317:3;6312:1;:8;6308:32;;6329:1;6332:6;;;;6323:7;6308:32;6354:3;6349:1;:8;6345:20;;6364:1;6359:6;;;;6345:20;5845:555;;;;:::o;1119:141:6:-;1235:3;1224:14;;;;1223:32;;1119:141::o;-1:-1:-1:-;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;:::o;5:130::-;72:20;;-1:-1;;;;;41055:54;;41879:35;;41869:2;;41928:1;;41918:12;160:352;;;290:3;283:4;275:6;271:17;267:27;257:2;;-1:-1;;298:12;257:2;-1:-1;328:20;;-1:-1;;;;;357:30;;354:2;;;-1:-1;;390:12;354:2;434:4;426:6;422:17;410:29;;485:3;434:4;;469:6;465:17;426:6;451:32;;448:41;445:2;;;502:1;;492:12;1456:241;;1560:2;1548:9;1539:7;1535:23;1531:32;1528:2;;;-1:-1;;1566:12;1528:2;1628:53;1673:7;1649:22;1628:53;;1704:366;;;1825:2;1813:9;1804:7;1800:23;1796:32;1793:2;;;-1:-1;;1831:12;1793:2;1893:53;1938:7;1914:22;1893:53;;;1883:63;1983:2;2022:22;;;;1106:20;;-1:-1;;;1787:283;2077:491;;;;2215:2;2203:9;2194:7;2190:23;2186:32;2183:2;;;-1:-1;;2221:12;2183:2;2283:53;2328:7;2304:22;2283:53;;;2273:63;2373:2;2412:22;;1106:20;;-1:-1;2481:2;2520:22;;;1106:20;;2177:391;-1:-1;;;2177:391;2575:617;;;;;2730:3;2718:9;2709:7;2705:23;2701:33;2698:2;;;-1:-1;;2737:12;2698:2;72:20;;-1:-1;;;;;41055:54;;41879:35;;41869:2;;-1:-1;;41918:12;41869:2;2789:63;2889:2;2928:22;;1106:20;;-1:-1;2997:2;3036:22;;1106:20;;3105:2;3144:22;1106:20;;-1:-1;2692:500;-1:-1;;;2692:500;3199:397;;;3338:2;3326:9;3317:7;3313:23;3309:32;3306:2;;;-1:-1;;3344:12;3306:2;3402:17;3389:31;-1:-1;;;;;3432:6;3429:30;3426:2;;;-1:-1;;3462:12;3426:2;3500:80;3572:7;3563:6;3552:9;3548:22;3500:80;;;3490:90;;;;-1:-1;3300:296;-1:-1;;;;3300:296;3603:929;;;;;;;3828:3;3816:9;3807:7;3803:23;3799:33;3796:2;;;-1:-1;;3835:12;3796:2;3893:17;3880:31;-1:-1;;;;;3931:18;3923:6;3920:30;3917:2;;;-1:-1;;3953:12;3917:2;3991:80;4063:7;4054:6;4043:9;4039:22;3991:80;;;3981:90;;-1:-1;3981:90;-1:-1;4136:2;4121:18;;4108:32;;-1:-1;4149:30;;;4146:2;;;-1:-1;;4182:12;4146:2;;4220:80;4292:7;4283:6;4272:9;4268:22;4220:80;;;3790:742;;;;-1:-1;4210:90;4337:2;4376:22;;1106:20;;4445:2;4484:22;;;1106:20;;-1:-1;3790:742;-1:-1;;;;3790:742;4539:647;;;;;4712:2;4700:9;4691:7;4687:23;4683:32;4680:2;;;-1:-1;;4718:12;4680:2;4776:17;4763:31;-1:-1;;;;;4806:6;4803:30;4800:2;;;-1:-1;;4836:12;4800:2;4874:80;4946:7;4937:6;4926:9;4922:22;4874:80;;;4864:90;;;;-1:-1;4991:2;5030:22;;1106:20;;5099:2;5138:22;1106:20;;-1:-1;4674:512;-1:-1;;;;4674:512;5193:533;;;;5341:2;5329:9;5320:7;5316:23;5312:32;5309:2;;;-1:-1;;5347:12;5309:2;982:6;976:13;994:33;1021:5;994:33;;;5510:2;5560:22;;976:13;5399:74;;-1:-1;994:33;976:13;994:33;;;5629:2;5678:22;;1394:13;5518:74;;-1:-1;41416:10;41405:22;;42250:34;;42240:2;;-1:-1;;42288:12;42240:2;5637:73;;;;5303:423;;;;;;5733:263;;5848:2;5836:9;5827:7;5823:23;5819:32;5816:2;;;-1:-1;;5854:12;5816:2;-1:-1;1254:13;;5810:186;-1:-1;5810:186;20561:674;20783:23;;41416:10;41405:22;24409:36;;20967:4;20956:16;;;20950:23;-1:-1;;;;;41183:70;;;21027:14;;;24301:37;;;;21139:4;21128:16;;;21122:23;41183:70;21199:14;;24301:37;20685:550;22103:507;22332:23;;-1:-1;;;;;41183:70;;;24301:37;;22514:4;22503:16;;;22497:23;41183:70;22574:14;;24301:37;22231:379;24457:392;-1:-1;;41792:2;41788:14;;;;;7378:58;;41788:14;;;;;24710:2;24701:12;;7378:58;24812:12;;;24601:248;24856:926;-1:-1;;;;;;16588:87;;41792:2;41788:14;;;;-1:-1;;41788:14;16573:1;16694:11;;7378:58;25468:12;;;12300:58;16200:66;25579:12;;;16180:87;16286:12;;;25202:580;25789:358;25960:2;25974:47;;;37746:12;;25945:18;;;39245:19;;;25789:358;;25960:2;36874:14;;;;39285;;;;25789:358;7866:251;7891:6;7888:1;7885:13;7866:251;;;7952:13;;40648;40641:21;12054:34;;38546:14;;;;6145;;;;7913:1;7906:9;7866:251;;;-1:-1;26027:110;;25931:216;-1:-1;;;;;;25931:216;26154:506;26399:2;26413:47;;;37746:12;;26384:18;;;39245:19;;;26154:506;;26399:2;36874:14;;;;39285;;;;26154:506;8814:362;8839:6;8836:1;8833:13;8814:362;;;6329:114;6439:3;8906:6;8900:13;6329:114;;;38546:14;;;;6472:4;6463:14;;;;;8861:1;8854:9;8814:362;;26667:514;26916:2;26930:47;;;37746:12;;26901:18;;;39245:19;;;26667:514;;26916:2;39285:14;;;;;;36874;;;26667:514;9887:368;9912:6;9909:1;9906:13;9887:368;;;6651:118;6765:3;9979:6;9973:13;6651:118;;;6789:14;;;;38546;;;;9934:1;9927:9;9887:368;;;-1:-1;26983:188;;26887:294;-1:-1;;;;;;;26887:294;27188:478;27419:2;27433:47;;;37746:12;;27404:18;;;39245:19;;;27188:478;;27419:2;36874:14;;;;39285;;;;27188:478;10899:341;10924:6;10921:1;10918:13;10899:341;;;10985:13;;23494:23;-1:-1;;;;;41183:70;24301:37;;38546:14;;;;7079;;;;41066:42;10939:9;10899:341;;27673:370;27850:2;27864:47;;;37746:12;;27835:18;;;39245:19;;;27673:370;;27850:2;36874:14;;;;39285;;;;27673:370;11709:260;11734:6;11731:1;11728:13;11709:260;;;11795:13;;-1:-1;;;;;40931:50;24071:37;;38546:14;;;;7261;;;;11756:1;11749:9;11709:260;;28050:210;40648:13;;40641:21;12054:34;;28171:2;28156:18;;28142:118;28267:416;28467:2;28481:47;;;12595:2;28452:18;;;39245:19;12631:34;39285:14;;;12611:55;-1:-1;;;12686:12;;;12679:36;12734:12;;;28438:245;28690:416;28890:2;28904:47;;;12985:2;28875:18;;;39245:19;13021:34;39285:14;;;13001:55;13090:34;13076:12;;;13069:56;-1:-1;;;13145:12;;;13138:30;13187:12;;;28861:245;29113:416;29313:2;29327:47;;;13438:2;29298:18;;;39245:19;13474:34;39285:14;;;13454:55;13543:34;13529:12;;;13522:56;-1:-1;;;13598:12;;;13591:34;13644:12;;;29284:245;29536:416;29736:2;29750:47;;;13895:2;29721:18;;;39245:19;13931:34;39285:14;;;13911:55;14000:34;13986:12;;;13979:56;-1:-1;;;14055:12;;;14048:40;14107:12;;;29707:245;29959:416;30159:2;30173:47;;;14358:2;30144:18;;;39245:19;14394:34;39285:14;;;14374:55;14463:34;14449:12;;;14442:56;-1:-1;;;14518:12;;;14511:33;14563:12;;;30130:245;30382:416;30582:2;30596:47;;;14814:2;30567:18;;;39245:19;14850:34;39285:14;;;14830:55;14919:34;14905:12;;;14898:56;-1:-1;;;14974:12;;;14967:31;15017:12;;;30553:245;30805:416;31005:2;31019:47;;;15268:2;30990:18;;;39245:19;15304:34;39285:14;;;15284:55;-1:-1;;;15359:12;;;15352:29;15400:12;;;30976:245;31228:416;31428:2;31442:47;;;15651:2;31413:18;;;39245:19;15687:34;39285:14;;;15667:55;15756:34;15742:12;;;15735:56;15825:32;15811:12;;;15804:54;15877:12;;;31399:245;31651:416;31851:2;31865:47;;;16944:2;31836:18;;;39245:19;16980:34;39285:14;;;16960:55;17049:34;17035:12;;;17028:56;-1:-1;;;17104:12;;;17097:30;17146:12;;;31822:245;32074:416;32274:2;32288:47;;;17397:2;32259:18;;;39245:19;17433:34;39285:14;;;17413:55;17502:34;17488:12;;;17481:56;-1:-1;;;17557:12;;;17550:30;17599:12;;;32245:245;32497:416;32697:2;32711:47;;;17850:2;32682:18;;;39245:19;17886:34;39285:14;;;17866:55;17955:34;17941:12;;;17934:56;-1:-1;;;18010:12;;;18003:31;18053:12;;;32668:245;32920:416;33120:2;33134:47;;;18304:2;33105:18;;;39245:19;18340:34;39285:14;;;18320:55;18409:34;18395:12;;;18388:56;18478:32;18464:12;;;18457:54;18530:12;;;33091:245;33343:416;33543:2;33557:47;;;18781:2;33528:18;;;39245:19;18817:34;39285:14;;;18797:55;-1:-1;;;18872:12;;;18865:27;18911:12;;;33514:245;33766:416;33966:2;33980:47;;;19162:2;33951:18;;;39245:19;19198:34;39285:14;;;19178:55;19267:34;19253:12;;;19246:56;-1:-1;;;19322:12;;;19315:45;19379:12;;;33937:245;34189:416;34389:2;34403:47;;;19630:2;34374:18;;;39245:19;19666:32;39285:14;;;19646:53;19718:12;;;34360:245;34612:416;34812:2;34826:47;;;19969:2;34797:18;;;39245:19;20005:34;39285:14;;;19985:55;20074:26;20060:12;;;20053:48;20120:12;;;34783:245;35035:416;35235:2;35249:47;;;20371:2;35220:18;;;39245:19;20407:25;39285:14;;;20387:46;20452:12;;;35206:245;35458:358;35653:2;35638:18;;35667:139;35642:9;35779:6;35667:139;;35823:366;36022:2;36007:18;;36036:143;36011:9;36152:6;36036:143;;36196:330;23494:23;;-1:-1;;;;;41183:70;24301:37;;36377:2;36362:18;;36348:178;36533:222;-1:-1;;;;;40931:50;;;;24071:37;;36660:2;36645:18;;36631:124;41944:117;-1:-1;;;;;42031:5;40815:42;42006:5;42003:35;41993:2;;42052:1;;42042:12;41993:2;41987:74;

Swarm Source

ipfs://a846e57523fbe71d04a80087a86961afe3195a7659fb3586d4c1945e4b0904c1
Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.