ETH Price: $3,231.06 (-1.00%)

Contract

0x01A903c12A2Dd87A5410173A29543504DF8bD14B
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Burn BMI To USDC143725912022-03-12 14:56:33976 days ago1647096993IN
BMIBurner
0 ETH0.0902713119.59558563
Burn BMI To USDC141043152022-01-30 2:02:141018 days ago1643508134IN
BMIBurner
0 ETH0.2359723656.84304491
Burn BMI To USDC138203002021-12-17 3:47:251062 days ago1639712845IN
BMIBurner
0 ETH0.2316581472.14615993
Burn BMI To USDC137706352021-12-09 10:54:371070 days ago1639047277IN
BMIBurner
0 ETH0.2044573849.01240111
Burn BMI To USDC137510082021-12-06 7:40:301073 days ago1638776430IN
BMIBurner
0 ETH0.3099897980.4269594
Burn BMI To USDC136568462021-11-21 7:33:381088 days ago1637480018IN
BMIBurner
0 ETH0.3362264358.53787211
Burn BMI To USDC136327152021-11-17 11:39:341092 days ago1637149174IN
BMIBurner
0 ETH0.4727424377.99671153
Burn BMI To USDC135882762021-11-10 11:38:411099 days ago1636544321IN
BMIBurner
0 ETH0.80096985141.87516367
Burn BMI To USDC135854612021-11-10 1:01:461099 days ago1636506106IN
BMIBurner
0 ETH1.01694546167.61535016
Burn BMI To USDC134840482021-10-25 3:04:331115 days ago1635131073IN
BMIBurner
0 ETH0.3487495587.6462157
Burn BMI To USDC134800252021-10-24 11:52:381116 days ago1635076358IN
BMIBurner
0 ETH0.1434185139.25843328
Burn BMI To USDC134727042021-10-23 8:27:551117 days ago1634977675IN
BMIBurner
0 ETH0.183665644.95024164
Burn BMI To USDC134594572021-10-21 6:37:551119 days ago1634798275IN
BMIBurner
0 ETH0.2528376455
Burn BMI To USDC134590732021-10-21 5:08:571119 days ago1634792937IN
BMIBurner
0 ETH0.2512297654
Burn BMI To USDC134542072021-10-20 10:56:571120 days ago1634727417IN
BMIBurner
0 ETH0.1792435243.05958322
Burn BMI To USDC134457162021-10-19 3:11:321121 days ago1634613092IN
BMIBurner
0 ETH0.2052515141.5778603
Burn BMI To USDC133104152021-09-27 21:59:461142 days ago1632779986IN
BMIBurner
0 ETH0.3606867267
Burn BMI To USDC133103382021-09-27 21:43:591142 days ago1632779039IN
BMIBurner
0 ETH0.15188145127
Burn BMI To USDC132732832021-09-22 3:56:231148 days ago1632282983IN
BMIBurner
0 ETH0.254886147.77887476
Burn BMI To USDC132291312021-09-15 8:12:281155 days ago1631693548IN
BMIBurner
0 ETH0.3057412662.30501966
Burn BMI To USDC131863412021-09-08 16:56:061161 days ago1631120166IN
BMIBurner
0 ETH1.7620278260
Burn BMI To USDC131103222021-08-27 23:06:081173 days ago1630105568IN
BMIBurner
0 ETH0.5134954371
Burn BMI To USDC130634442021-08-20 17:21:401180 days ago1629480100IN
BMIBurner
0 ETH0.2121524335
Burn BMI To USDC130630742021-08-20 16:04:011180 days ago1629475441IN
BMIBurner
0 ETH0.2859643240
Burn BMI To USDC130617442021-08-20 10:59:051181 days ago1629457145IN
BMIBurner
0 ETH0.1806544529
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
BMIBurner

Compiler Version
v0.7.3+commit.9bfce1f6

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity Multiple files format)

File 1 of 17: BMIBurner.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

import "./IBasket.sol";

import "./BMIZapper.sol";

contract BMIBurner is BMIZapper {
    using SafeERC20 for IERC20;

    constructor() {}

    function burnBMIToUSDC(uint256 _amount, uint256 _minRecv) public returns (uint256) {
        // Burn BMI
        IERC20(BMI).safeTransferFrom(msg.sender, address(this), _amount);
        (address[] memory constituients, ) = IBasket(BMI).getAssetsAndBalances();
        IBasket(BMI).burn(_amount);

        // Convert BMI
        for (uint256 i = 0; i < constituients.length; i++) {
            _fromBMIConstituentToUSDC(constituients[i], IERC20(constituients[i]).balanceOf(address(this)));
        }
        uint256 usdcBal = IERC20(USDC).balanceOf(address(this));
        require(usdcBal >= _minRecv, "!min-usdc");
        IERC20(USDC).safeTransfer(msg.sender, usdcBal);

        return usdcBal;
    }
}

File 2 of 17: ABDKMath64x64.sol
// SPDX-License-Identifier: BSD-4-Clause
/*
 * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.
 * Author: Mikhail Vladimirov <[email protected]>
 */
pragma solidity ^0.7.0;

/**
 * Smart contract library of mathematical functions operating with signed
 * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is
 * basically a simple fraction whose numerator is signed 128-bit integer and
 * denominator is 2^64.  As long as denominator is always the same, there is no
 * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are
 * represented by int128 type holding only the numerator.
 */
library ABDKMath64x64 {
  /*
   * Minimum value signed 64.64-bit fixed point number may have. 
   */
  int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;

  /*
   * Maximum value signed 64.64-bit fixed point number may have. 
   */
  int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

  /**
   * Convert signed 256-bit integer number into signed 64.64-bit fixed point
   * number.  Revert on overflow.
   *
   * @param x signed 256-bit integer number
   * @return signed 64.64-bit fixed point number
   */
  function fromInt (int256 x) internal pure returns (int128) {
    require (x >= -0x8000000000000000 && x <= 0x7FFFFFFFFFFFFFFF);
    return int128 (x << 64);
  }

  /**
   * Convert signed 64.64 fixed point number into signed 64-bit integer number
   * rounding down.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64-bit integer number
   */
  function toInt (int128 x) internal pure returns (int64) {
    return int64 (x >> 64);
  }

  /**
   * Convert unsigned 256-bit integer number into signed 64.64-bit fixed point
   * number.  Revert on overflow.
   *
   * @param x unsigned 256-bit integer number
   * @return signed 64.64-bit fixed point number
   */
  function fromUInt (uint256 x) internal pure returns (int128) {
    require (x <= 0x7FFFFFFFFFFFFFFF);
    return int128 (x << 64);
  }

  /**
   * Convert signed 64.64 fixed point number into unsigned 64-bit integer
   * number rounding down.  Revert on underflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return unsigned 64-bit integer number
   */
  function toUInt (int128 x) internal pure returns (uint64) {
    require (x >= 0);
    return uint64 (x >> 64);
  }

  /**
   * Convert signed 128.128 fixed point number into signed 64.64-bit fixed point
   * number rounding down.  Revert on overflow.
   *
   * @param x signed 128.128-bin fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function from128x128 (int256 x) internal pure returns (int128) {
    int256 result = x >> 64;
    require (result >= MIN_64x64 && result <= MAX_64x64);
    return int128 (result);
  }

  /**
   * Convert signed 64.64 fixed point number into signed 128.128 fixed point
   * number.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 128.128 fixed point number
   */
  function to128x128 (int128 x) internal pure returns (int256) {
    return int256 (x) << 64;
  }

  /**
   * Calculate x + y.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function add (int128 x, int128 y) internal pure returns (int128) {
    int256 result = int256(x) + y;
    require (result >= MIN_64x64 && result <= MAX_64x64);
    return int128 (result);
  }

  /**
   * Calculate x - y.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function sub (int128 x, int128 y) internal pure returns (int128) {
    int256 result = int256(x) - y;
    require (result >= MIN_64x64 && result <= MAX_64x64);
    return int128 (result);
  }

  /**
   * Calculate x * y rounding down.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function mul (int128 x, int128 y) internal pure returns (int128) {
    int256 result = int256(x) * y >> 64;
    require (result >= MIN_64x64 && result <= MAX_64x64);
    return int128 (result);
  }

  /**
   * Calculate x * y rounding towards zero, where x is signed 64.64 fixed point
   * number and y is signed 256-bit integer number.  Revert on overflow.
   *
   * @param x signed 64.64 fixed point number
   * @param y signed 256-bit integer number
   * @return signed 256-bit integer number
   */
  function muli (int128 x, int256 y) internal pure returns (int256) {
    if (x == MIN_64x64) {
      require (y >= -0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF &&
        y <= 0x1000000000000000000000000000000000000000000000000);
      return -y << 63;
    } else {
      bool negativeResult = false;
      if (x < 0) {
        x = -x;
        negativeResult = true;
      }
      if (y < 0) {
        y = -y; // We rely on overflow behavior here
        negativeResult = !negativeResult;
      }
      uint256 absoluteResult = mulu (x, uint256 (y));
      if (negativeResult) {
        require (absoluteResult <=
          0x8000000000000000000000000000000000000000000000000000000000000000);
        return -int256 (absoluteResult); // We rely on overflow behavior here
      } else {
        require (absoluteResult <=
          0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
        return int256 (absoluteResult);
      }
    }
  }

  /**
   * Calculate x * y rounding down, where x is signed 64.64 fixed point number
   * and y is unsigned 256-bit integer number.  Revert on overflow.
   *
   * @param x signed 64.64 fixed point number
   * @param y unsigned 256-bit integer number
   * @return unsigned 256-bit integer number
   */
  function mulu (int128 x, uint256 y) internal pure returns (uint256) {
    if (y == 0) return 0;

    require (x >= 0);

    uint256 lo = (uint256 (x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;
    uint256 hi = uint256 (x) * (y >> 128);

    require (hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
    hi <<= 64;

    require (hi <=
      0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo);
    return hi + lo;
  }

  /**
   * Calculate x / y rounding towards zero.  Revert on overflow or when y is
   * zero.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function div (int128 x, int128 y) internal pure returns (int128) {
    require (y != 0);
    int256 result = (int256 (x) << 64) / y;
    require (result >= MIN_64x64 && result <= MAX_64x64);
    return int128 (result);
  }

  /**
   * Calculate x / y rounding towards zero, where x and y are signed 256-bit
   * integer numbers.  Revert on overflow or when y is zero.
   *
   * @param x signed 256-bit integer number
   * @param y signed 256-bit integer number
   * @return signed 64.64-bit fixed point number
   */
  function divi (int256 x, int256 y) internal pure returns (int128) {
    require (y != 0);

    bool negativeResult = false;
    if (x < 0) {
      x = -x; // We rely on overflow behavior here
      negativeResult = true;
    }
    if (y < 0) {
      y = -y; // We rely on overflow behavior here
      negativeResult = !negativeResult;
    }
    uint128 absoluteResult = divuu (uint256 (x), uint256 (y));
    if (negativeResult) {
      require (absoluteResult <= 0x80000000000000000000000000000000);
      return -int128 (absoluteResult); // We rely on overflow behavior here
    } else {
      require (absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
      return int128 (absoluteResult); // We rely on overflow behavior here
    }
  }

  /**
   * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit
   * integer numbers.  Revert on overflow or when y is zero.
   *
   * @param x unsigned 256-bit integer number
   * @param y unsigned 256-bit integer number
   * @return signed 64.64-bit fixed point number
   */
  function divu (uint256 x, uint256 y) internal pure returns (int128) {
    require (y != 0);
    uint128 result = divuu (x, y);
    require (result <= uint128 (MAX_64x64));
    return int128 (result);
  }

  /**
   * Calculate -x.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function neg (int128 x) internal pure returns (int128) {
    require (x != MIN_64x64);
    return -x;
  }

  /**
   * Calculate |x|.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function abs (int128 x) internal pure returns (int128) {
    require (x != MIN_64x64);
    return x < 0 ? -x : x;
  }

  /**
   * Calculate 1 / x rounding towards zero.  Revert on overflow or when x is
   * zero.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function inv (int128 x) internal pure returns (int128) {
    require (x != 0);
    int256 result = int256 (0x100000000000000000000000000000000) / x;
    require (result >= MIN_64x64 && result <= MAX_64x64);
    return int128 (result);
  }

  /**
   * Calculate arithmetics average of x and y, i.e. (x + y) / 2 rounding down.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function avg (int128 x, int128 y) internal pure returns (int128) {
    return int128 ((int256 (x) + int256 (y)) >> 1);
  }

  /**
   * Calculate geometric average of x and y, i.e. sqrt (x * y) rounding down.
   * Revert on overflow or in case x * y is negative.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function gavg (int128 x, int128 y) internal pure returns (int128) {
    int256 m = int256 (x) * int256 (y);
    require (m >= 0);
    require (m <
        0x4000000000000000000000000000000000000000000000000000000000000000);
    return int128 (sqrtu (uint256 (m)));
  }

  /**
   * Calculate x^y assuming 0^0 is 1, where x is signed 64.64 fixed point number
   * and y is unsigned 256-bit integer number.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y uint256 value
   * @return signed 64.64-bit fixed point number
   */
  function pow (int128 x, uint256 y) internal pure returns (int128) {
    uint256 absoluteResult;
    bool negativeResult = false;
    if (x >= 0) {
      absoluteResult = powu (uint256 (x) << 63, y);
    } else {
      // We rely on overflow behavior here
      absoluteResult = powu (uint256 (uint128 (-x)) << 63, y);
      negativeResult = y & 1 > 0;
    }

    absoluteResult >>= 63;

    if (negativeResult) {
      require (absoluteResult <= 0x80000000000000000000000000000000);
      return -int128 (absoluteResult); // We rely on overflow behavior here
    } else {
      require (absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
      return int128 (absoluteResult); // We rely on overflow behavior here
    }
  }

  /**
   * Calculate sqrt (x) rounding down.  Revert if x < 0.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function sqrt (int128 x) internal pure returns (int128) {
    require (x >= 0);
    return int128 (sqrtu (uint256 (x) << 64));
  }

  /**
   * Calculate binary logarithm of x.  Revert if x <= 0.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function log_2 (int128 x) internal pure returns (int128) {
    require (x > 0);

    int256 msb = 0;
    int256 xc = x;
    if (xc >= 0x10000000000000000) { xc >>= 64; msb += 64; }
    if (xc >= 0x100000000) { xc >>= 32; msb += 32; }
    if (xc >= 0x10000) { xc >>= 16; msb += 16; }
    if (xc >= 0x100) { xc >>= 8; msb += 8; }
    if (xc >= 0x10) { xc >>= 4; msb += 4; }
    if (xc >= 0x4) { xc >>= 2; msb += 2; }
    if (xc >= 0x2) msb += 1;  // No need to shift xc anymore

    int256 result = msb - 64 << 64;
    uint256 ux = uint256 (x) << uint256 (127 - msb);
    for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {
      ux *= ux;
      uint256 b = ux >> 255;
      ux >>= 127 + b;
      result += bit * int256 (b);
    }

    return int128 (result);
  }

  /**
   * Calculate natural logarithm of x.  Revert if x <= 0.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function ln (int128 x) internal pure returns (int128) {
    require (x > 0);

    return int128 (
        uint256 (log_2 (x)) * 0xB17217F7D1CF79ABC9E3B39803F2F6AF >> 128);
  }

  /**
   * Calculate binary exponent of x.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function exp_2 (int128 x) internal pure returns (int128) {
    require (x < 0x400000000000000000); // Overflow

    if (x < -0x400000000000000000) return 0; // Underflow

    uint256 result = 0x80000000000000000000000000000000;

    if (x & 0x8000000000000000 > 0)
      result = result * 0x16A09E667F3BCC908B2FB1366EA957D3E >> 128;
    if (x & 0x4000000000000000 > 0)
      result = result * 0x1306FE0A31B7152DE8D5A46305C85EDEC >> 128;
    if (x & 0x2000000000000000 > 0)
      result = result * 0x1172B83C7D517ADCDF7C8C50EB14A791F >> 128;
    if (x & 0x1000000000000000 > 0)
      result = result * 0x10B5586CF9890F6298B92B71842A98363 >> 128;
    if (x & 0x800000000000000 > 0)
      result = result * 0x1059B0D31585743AE7C548EB68CA417FD >> 128;
    if (x & 0x400000000000000 > 0)
      result = result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8 >> 128;
    if (x & 0x200000000000000 > 0)
      result = result * 0x10163DA9FB33356D84A66AE336DCDFA3F >> 128;
    if (x & 0x100000000000000 > 0)
      result = result * 0x100B1AFA5ABCBED6129AB13EC11DC9543 >> 128;
    if (x & 0x80000000000000 > 0)
      result = result * 0x10058C86DA1C09EA1FF19D294CF2F679B >> 128;
    if (x & 0x40000000000000 > 0)
      result = result * 0x1002C605E2E8CEC506D21BFC89A23A00F >> 128;
    if (x & 0x20000000000000 > 0)
      result = result * 0x100162F3904051FA128BCA9C55C31E5DF >> 128;
    if (x & 0x10000000000000 > 0)
      result = result * 0x1000B175EFFDC76BA38E31671CA939725 >> 128;
    if (x & 0x8000000000000 > 0)
      result = result * 0x100058BA01FB9F96D6CACD4B180917C3D >> 128;
    if (x & 0x4000000000000 > 0)
      result = result * 0x10002C5CC37DA9491D0985C348C68E7B3 >> 128;
    if (x & 0x2000000000000 > 0)
      result = result * 0x1000162E525EE054754457D5995292026 >> 128;
    if (x & 0x1000000000000 > 0)
      result = result * 0x10000B17255775C040618BF4A4ADE83FC >> 128;
    if (x & 0x800000000000 > 0)
      result = result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB >> 128;
    if (x & 0x400000000000 > 0)
      result = result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9 >> 128;
    if (x & 0x200000000000 > 0)
      result = result * 0x10000162E43F4F831060E02D839A9D16D >> 128;
    if (x & 0x100000000000 > 0)
      result = result * 0x100000B1721BCFC99D9F890EA06911763 >> 128;
    if (x & 0x80000000000 > 0)
      result = result * 0x10000058B90CF1E6D97F9CA14DBCC1628 >> 128;
    if (x & 0x40000000000 > 0)
      result = result * 0x1000002C5C863B73F016468F6BAC5CA2B >> 128;
    if (x & 0x20000000000 > 0)
      result = result * 0x100000162E430E5A18F6119E3C02282A5 >> 128;
    if (x & 0x10000000000 > 0)
      result = result * 0x1000000B1721835514B86E6D96EFD1BFE >> 128;
    if (x & 0x8000000000 > 0)
      result = result * 0x100000058B90C0B48C6BE5DF846C5B2EF >> 128;
    if (x & 0x4000000000 > 0)
      result = result * 0x10000002C5C8601CC6B9E94213C72737A >> 128;
    if (x & 0x2000000000 > 0)
      result = result * 0x1000000162E42FFF037DF38AA2B219F06 >> 128;
    if (x & 0x1000000000 > 0)
      result = result * 0x10000000B17217FBA9C739AA5819F44F9 >> 128;
    if (x & 0x800000000 > 0)
      result = result * 0x1000000058B90BFCDEE5ACD3C1CEDC823 >> 128;
    if (x & 0x400000000 > 0)
      result = result * 0x100000002C5C85FE31F35A6A30DA1BE50 >> 128;
    if (x & 0x200000000 > 0)
      result = result * 0x10000000162E42FF0999CE3541B9FFFCF >> 128;
    if (x & 0x100000000 > 0)
      result = result * 0x100000000B17217F80F4EF5AADDA45554 >> 128;
    if (x & 0x80000000 > 0)
      result = result * 0x10000000058B90BFBF8479BD5A81B51AD >> 128;
    if (x & 0x40000000 > 0)
      result = result * 0x1000000002C5C85FDF84BD62AE30A74CC >> 128;
    if (x & 0x20000000 > 0)
      result = result * 0x100000000162E42FEFB2FED257559BDAA >> 128;
    if (x & 0x10000000 > 0)
      result = result * 0x1000000000B17217F7D5A7716BBA4A9AE >> 128;
    if (x & 0x8000000 > 0)
      result = result * 0x100000000058B90BFBE9DDBAC5E109CCE >> 128;
    if (x & 0x4000000 > 0)
      result = result * 0x10000000002C5C85FDF4B15DE6F17EB0D >> 128;
    if (x & 0x2000000 > 0)
      result = result * 0x1000000000162E42FEFA494F1478FDE05 >> 128;
    if (x & 0x1000000 > 0)
      result = result * 0x10000000000B17217F7D20CF927C8E94C >> 128;
    if (x & 0x800000 > 0)
      result = result * 0x1000000000058B90BFBE8F71CB4E4B33D >> 128;
    if (x & 0x400000 > 0)
      result = result * 0x100000000002C5C85FDF477B662B26945 >> 128;
    if (x & 0x200000 > 0)
      result = result * 0x10000000000162E42FEFA3AE53369388C >> 128;
    if (x & 0x100000 > 0)
      result = result * 0x100000000000B17217F7D1D351A389D40 >> 128;
    if (x & 0x80000 > 0)
      result = result * 0x10000000000058B90BFBE8E8B2D3D4EDE >> 128;
    if (x & 0x40000 > 0)
      result = result * 0x1000000000002C5C85FDF4741BEA6E77E >> 128;
    if (x & 0x20000 > 0)
      result = result * 0x100000000000162E42FEFA39FE95583C2 >> 128;
    if (x & 0x10000 > 0)
      result = result * 0x1000000000000B17217F7D1CFB72B45E1 >> 128;
    if (x & 0x8000 > 0)
      result = result * 0x100000000000058B90BFBE8E7CC35C3F0 >> 128;
    if (x & 0x4000 > 0)
      result = result * 0x10000000000002C5C85FDF473E242EA38 >> 128;
    if (x & 0x2000 > 0)
      result = result * 0x1000000000000162E42FEFA39F02B772C >> 128;
    if (x & 0x1000 > 0)
      result = result * 0x10000000000000B17217F7D1CF7D83C1A >> 128;
    if (x & 0x800 > 0)
      result = result * 0x1000000000000058B90BFBE8E7BDCBE2E >> 128;
    if (x & 0x400 > 0)
      result = result * 0x100000000000002C5C85FDF473DEA871F >> 128;
    if (x & 0x200 > 0)
      result = result * 0x10000000000000162E42FEFA39EF44D91 >> 128;
    if (x & 0x100 > 0)
      result = result * 0x100000000000000B17217F7D1CF79E949 >> 128;
    if (x & 0x80 > 0)
      result = result * 0x10000000000000058B90BFBE8E7BCE544 >> 128;
    if (x & 0x40 > 0)
      result = result * 0x1000000000000002C5C85FDF473DE6ECA >> 128;
    if (x & 0x20 > 0)
      result = result * 0x100000000000000162E42FEFA39EF366F >> 128;
    if (x & 0x10 > 0)
      result = result * 0x1000000000000000B17217F7D1CF79AFA >> 128;
    if (x & 0x8 > 0)
      result = result * 0x100000000000000058B90BFBE8E7BCD6D >> 128;
    if (x & 0x4 > 0)
      result = result * 0x10000000000000002C5C85FDF473DE6B2 >> 128;
    if (x & 0x2 > 0)
      result = result * 0x1000000000000000162E42FEFA39EF358 >> 128;
    if (x & 0x1 > 0)
      result = result * 0x10000000000000000B17217F7D1CF79AB >> 128;

    result >>= uint256 (63 - (x >> 64));
    require (result <= uint256 (MAX_64x64));

    return int128 (result);
  }

  /**
   * Calculate natural exponent of x.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function exp (int128 x) internal pure returns (int128) {
    require (x < 0x400000000000000000); // Overflow

    if (x < -0x400000000000000000) return 0; // Underflow

    return exp_2 (
        int128 (int256 (x) * 0x171547652B82FE1777D0FFDA0D23A7D12 >> 128));
  }

  /**
   * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit
   * integer numbers.  Revert on overflow or when y is zero.
   *
   * @param x unsigned 256-bit integer number
   * @param y unsigned 256-bit integer number
   * @return unsigned 64.64-bit fixed point number
   */
  function divuu (uint256 x, uint256 y) private pure returns (uint128) {
    require (y != 0);

    uint256 result;

    if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
      result = (x << 64) / y;
    else {
      uint256 msb = 192;
      uint256 xc = x >> 192;
      if (xc >= 0x100000000) { xc >>= 32; msb += 32; }
      if (xc >= 0x10000) { xc >>= 16; msb += 16; }
      if (xc >= 0x100) { xc >>= 8; msb += 8; }
      if (xc >= 0x10) { xc >>= 4; msb += 4; }
      if (xc >= 0x4) { xc >>= 2; msb += 2; }
      if (xc >= 0x2) msb += 1;  // No need to shift xc anymore

      result = (x << 255 - msb) / ((y - 1 >> msb - 191) + 1);
      require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);

      uint256 hi = result * (y >> 128);
      uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);

      uint256 xh = x >> 192;
      uint256 xl = x << 64;

      if (xl < lo) xh -= 1;
      xl -= lo; // We rely on overflow behavior here
      lo = hi << 128;
      if (xl < lo) xh -= 1;
      xl -= lo; // We rely on overflow behavior here

      assert (xh == hi >> 128);

      result += xl / y;
    }

    require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
    return uint128 (result);
  }

  /**
   * Calculate x^y assuming 0^0 is 1, where x is unsigned 129.127 fixed point
   * number and y is unsigned 256-bit integer number.  Revert on overflow.
   *
   * @param x unsigned 129.127-bit fixed point number
   * @param y uint256 value
   * @return unsigned 129.127-bit fixed point number
   */
  function powu (uint256 x, uint256 y) private pure returns (uint256) {
    if (y == 0) return 0x80000000000000000000000000000000;
    else if (x == 0) return 0;
    else {
      int256 msb = 0;
      uint256 xc = x;
      if (xc >= 0x100000000000000000000000000000000) { xc >>= 128; msb += 128; }
      if (xc >= 0x10000000000000000) { xc >>= 64; msb += 64; }
      if (xc >= 0x100000000) { xc >>= 32; msb += 32; }
      if (xc >= 0x10000) { xc >>= 16; msb += 16; }
      if (xc >= 0x100) { xc >>= 8; msb += 8; }
      if (xc >= 0x10) { xc >>= 4; msb += 4; }
      if (xc >= 0x4) { xc >>= 2; msb += 2; }
      if (xc >= 0x2) msb += 1;  // No need to shift xc anymore

      int256 xe = msb - 127;
      if (xe > 0) x >>= uint256 (xe);
      else x <<= uint256 (-xe);

      uint256 result = 0x80000000000000000000000000000000;
      int256 re = 0;

      while (y > 0) {
        if (y & 1 > 0) {
          result = result * x;
          y -= 1;
          re += xe;
          if (result >=
            0x8000000000000000000000000000000000000000000000000000000000000000) {
            result >>= 128;
            re += 1;
          } else result >>= 127;
          if (re < -127) return 0; // Underflow
          require (re < 128); // Overflow
        } else {
          x = x * x;
          y >>= 1;
          xe <<= 1;
          if (x >=
            0x8000000000000000000000000000000000000000000000000000000000000000) {
            x >>= 128;
            xe += 1;
          } else x >>= 127;
          if (xe < -127) return 0; // Underflow
          require (xe < 128); // Overflow
        }
      }

      if (re > 0) result <<= uint256 (re);
      else if (re < 0) result >>= uint256 (-re);

      return result;
    }
  }

  /**
   * Calculate sqrt (x) rounding down, where x is unsigned 256-bit integer
   * number.
   *
   * @param x unsigned 256-bit integer number
   * @return unsigned 128-bit integer number
   */
  function sqrtu (uint256 x) private pure returns (uint128) {
    if (x == 0) return 0;
    else {
      uint256 xx = x;
      uint256 r = 1;
      if (xx >= 0x100000000000000000000000000000000) { xx >>= 128; r <<= 64; }
      if (xx >= 0x10000000000000000) { xx >>= 64; r <<= 32; }
      if (xx >= 0x100000000) { xx >>= 32; r <<= 16; }
      if (xx >= 0x10000) { xx >>= 16; r <<= 8; }
      if (xx >= 0x100) { xx >>= 8; r <<= 4; }
      if (xx >= 0x10) { xx >>= 4; r <<= 2; }
      if (xx >= 0x8) { r <<= 1; }
      r = (r + x / r) >> 1;
      r = (r + x / r) >> 1;
      r = (r + x / r) >> 1;
      r = (r + x / r) >> 1;
      r = (r + x / r) >> 1;
      r = (r + x / r) >> 1;
      r = (r + x / r) >> 1; // Seven iterations should be enough
      uint256 r1 = x / r;
      return uint128 (r < r1 ? r : r1);
    }
  }
}

File 3 of 17: Address.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 4 of 17: BMIZapper.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

import "./ICToken.sol";
import "./IYearn.sol";
import "./ILendingPoolV2.sol";
import "./IBasket.sol";
import "./IATokenV2.sol";
import "./ICurveZap.sol";
import "./ICurve.sol";

import "./ABDKMath64x64.sol";

import "./ERC20.sol";
import "./IERC20.sol";
import "./SafeERC20.sol";
import "./SafeMath.sol";
import "./Ownable.sol";

contract BMIZapper is Ownable {
    using SafeERC20 for IERC20;
    using SafeMath for uint256;

    using ABDKMath64x64 for int128;
    using ABDKMath64x64 for uint256;

    // Auxillery
    address constant AAVE_LENDING_POOL_V2 = 0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9;

    // Tokens

    // BMI
    address constant BMI = 0x0aC00355F80E289f53BF368C9Bdb70f5c114C44B;

    // Bare
    address constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
    address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
    address constant USDT = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
    address constant TUSD = 0x0000000000085d4780B73119b644AE5ecd22b376;
    address constant SUSD = 0x57Ab1ec28D129707052df4dF418D58a2D46d5f51;
    address constant BUSD = 0x4Fabb145d64652a948d72533023f6E7A623C7C53;
    address constant USDP = 0x1456688345527bE1f37E9e627DA0837D6f08C925;
    address constant FRAX = 0x853d955aCEf822Db058eb8505911ED77F175b99e;
    address constant ALUSD = 0xBC6DA0FE9aD5f3b0d58160288917AA56653660E9;
    address constant LUSD = 0x5f98805A4E8be255a32880FDeC7F6728C6568bA0;
    address constant USDN = 0x674C6Ad92Fd080e4004b2312b45f796a192D27a0;

    // Yearn
    address constant yDAI = 0x19D3364A399d251E894aC732651be8B0E4e85001;
    address constant yUSDC = 0x5f18C75AbDAe578b483E5F43f12a39cF75b973a9;
    address constant yUSDT = 0x7Da96a3891Add058AdA2E826306D812C638D87a7;
    address constant yTUSD = 0x37d19d1c4E1fa9DC47bD1eA12f742a0887eDa74a;
    address constant ySUSD = 0xa5cA62D95D24A4a350983D5B8ac4EB8638887396;

    // Yearn CRV
    address constant yCRV = 0x4B5BfD52124784745c1071dcB244C6688d2533d3; // Y Pool
    address constant ycrvSUSD = 0x5a770DbD3Ee6bAF2802D29a901Ef11501C44797A;
    address constant ycrvYBUSD = 0x8ee57c05741aA9DB947A744E713C15d4d19D8822;
    address constant ycrvBUSD = 0x6Ede7F19df5df6EF23bD5B9CeDb651580Bdf56Ca;
    address constant ycrvUSDP = 0xC4dAf3b5e2A9e93861c3FBDd25f1e943B8D87417;
    address constant ycrvFRAX = 0xB4AdA607B9d6b2c9Ee07A275e9616B84AC560139;
    address constant ycrvALUSD = 0xA74d4B67b3368E83797a35382AFB776bAAE4F5C8;
    address constant ycrvLUSD = 0x5fA5B62c8AF877CB37031e0a3B2f34A78e3C56A6;
    address constant ycrvUSDN = 0x3B96d491f067912D18563d56858Ba7d6EC67a6fa;
    address constant ycrvIB = 0x27b7b1ad7288079A66d12350c828D3C00A6F07d7;
    address constant ycrvThree = 0x84E13785B5a27879921D6F685f041421C7F482dA;
    address constant ycrvDUSD = 0x30FCf7c6cDfC46eC237783D94Fc78553E79d4E9C;
    address constant ycrvMUSD = 0x8cc94ccd0f3841a468184aCA3Cc478D2148E1757;
    address constant ycrvUST = 0x1C6a9783F812b3Af3aBbf7de64c3cD7CC7D1af44;

    // Aave
    address constant aDAI = 0x028171bCA77440897B824Ca71D1c56caC55b68A3;
    address constant aUSDC = 0xBcca60bB61934080951369a648Fb03DF4F96263C;
    address constant aUSDT = 0x3Ed3B47Dd13EC9a98b44e6204A523E766B225811;
    address constant aTUSD = 0x101cc05f4A51C0319f570d5E146a8C625198e636;
    address constant aSUSD = 0x6C5024Cd4F8A59110119C56f8933403A539555EB;

    // Compound
    address constant cDAI = 0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643;
    address constant cUSDC = 0x39AA39c021dfbaE8faC545936693aC917d5E7563;
    address constant cUSDT = 0xf650C3d88D12dB855b8bf7D11Be6C55A4e07dCC9;
    address constant cTUSD = 0x12392F67bdf24faE0AF363c24aC620a2f67DAd86;

    // Curve
    address constant crvY = 0xdF5e0e81Dff6FAF3A7e52BA697820c5e32D806A8;
    address constant crvYPool = 0x45F783CCE6B7FF23B2ab2D70e416cdb7D6055f51;
    address constant crvYZap = 0xbBC81d23Ea2c3ec7e56D39296F0cbB648873a5d3;

    address constant crvSUSD = 0xC25a3A3b969415c80451098fa907EC722572917F;
    address constant crvSUSDPool = 0xA5407eAE9Ba41422680e2e00537571bcC53efBfD;
    address constant crvSUSDZap = 0xFCBa3E75865d2d561BE8D220616520c171F12851;

    address constant crvYBUSD = 0x3B3Ac5386837Dc563660FB6a0937DFAa5924333B;
    address constant crvYBUSDPool = 0x79a8C46DeA5aDa233ABaFFD40F3A0A2B1e5A4F27;
    address constant crvYBUSDZap = 0xb6c057591E073249F2D9D88Ba59a46CFC9B59EdB;

    address constant crvThree = 0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490;
    address constant crvThreePool = 0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7;

    address constant crvUSDP = 0x7Eb40E450b9655f4B3cC4259BCC731c63ff55ae6;
    address constant crvUSDPPool = 0x42d7025938bEc20B69cBae5A77421082407f053A;
    address constant crvUSDPZap = 0x3c8cAee4E09296800f8D29A68Fa3837e2dae4940;

    address constant crvDUSD = 0x3a664Ab939FD8482048609f652f9a0B0677337B9;
    address constant crvDUSDPool = 0x8038C01A0390a8c547446a0b2c18fc9aEFEcc10c;
    address constant crvDUSDZap = 0x61E10659fe3aa93d036d099405224E4Ac24996d0;

    address constant crvMUSD = 0x1AEf73d49Dedc4b1778d0706583995958Dc862e6;
    address constant crvMUSDPool = 0x8474DdbE98F5aA3179B3B3F5942D724aFcdec9f6;
    address constant crvMUSDZap = 0x803A2B40c5a9BB2B86DD630B274Fa2A9202874C2;

    address constant crvUST = 0x94e131324b6054c0D789b190b2dAC504e4361b53;
    address constant crvUSTPool = 0x890f4e345B1dAED0367A877a1612f86A1f86985f;
    address constant crvUSTZap = 0xB0a0716841F2Fc03fbA72A891B8Bb13584F52F2d;

    address constant crvUSDN = 0x4f3E8F405CF5aFC05D68142F3783bDfE13811522;
    address constant crvUSDNPool = 0x0f9cb53Ebe405d49A0bbdBD291A65Ff571bC83e1;
    address constant crvUSDNZap = 0x094d12e5b541784701FD8d65F11fc0598FBC6332;

    address constant crvIB = 0x5282a4eF67D9C33135340fB3289cc1711c13638C;
    address constant crvIBPool = 0x2dded6Da1BF5DBdF597C45fcFaa3194e53EcfeAF;

    address constant crvBUSD = 0x4807862AA8b2bF68830e4C8dc86D0e9A998e085a;
    address constant crvFRAX = 0xd632f22692FaC7611d2AA1C0D552930D43CAEd3B;
    address constant crvALUSD = 0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c;
    address constant crvLUSD = 0xEd279fDD11cA84bEef15AF5D39BB4d4bEE23F0cA;

    address constant crvMetaZapper = 0xA79828DF1850E8a3A3064576f380D90aECDD3359;

    // **** Constructor ****

    constructor() {}

    function recoverERC20(address _token) public onlyOwner {
        IERC20(_token).safeTransfer(msg.sender, IERC20(_token).balanceOf(address(this)));
    }

    function recoverERC20s(address[] memory _tokens) public onlyOwner {
        for (uint256 i = 0; i < _tokens.length; i++) {
            IERC20(_tokens[i]).safeTransfer(msg.sender, IERC20(_tokens[i]).balanceOf(address(this)));
        }
    }

    // **** View only functions **** //

    // Estimates USDC equilavent for yearn crv and crv pools
    function calcUSDCEquilavent(address _from, uint256 _amount) public view returns (uint256) {
        if (_isYearnCRV(_from)) {
            _amount = _amount.mul(IYearn(_from).pricePerShare()).div(1e18);
            _from = IYearn(_from).token();
        }

        if (_from == crvY || _from == crvSUSD || _from == crvThree || _from == crvYBUSD) {
            address zap = crvYZap;

            if (_from == crvSUSD) {
                zap = crvSUSDZap;
            } else if (_from == crvThree) {
                zap = crvThreePool;
            } else if (_from == crvYBUSD) {
                zap = crvYBUSDZap;
            }

            return ICurveZapSimple(zap).calc_withdraw_one_coin(_amount, 1);
        } else if (_from == crvUSDN || _from == crvUSDP || _from == crvDUSD || _from == crvMUSD || _from == crvUST) {
            address zap = crvUSDNZap;

            if (_from == crvUSDP) {
                zap = crvUSDPZap;
            } else if (_from == crvDUSD) {
                zap = crvDUSDZap;
            } else if (_from == crvMUSD) {
                zap = crvMUSDZap;
            } else if (_from == crvUST) {
                zap = crvUSTZap;
            }

            return ICurveZapSimple(zap).calc_withdraw_one_coin(_amount, 2);
        } else if (_from == crvIB) {
            return ICurveZapSimple(crvIBPool).calc_withdraw_one_coin(_amount, 1, true);
        } else {
            // Meta pools, USDC is 2nd index
            return ICurveZapSimple(crvMetaZapper).calc_withdraw_one_coin(_from, _amount, 2);
        }
    }

    function getUnderlyingAmount(address _derivative, uint256 _amount) public view returns (address, uint256) {
        if (_isAave(_derivative)) {
            return (IATokenV2(_derivative).UNDERLYING_ASSET_ADDRESS(), _amount);
        }

        if (_isCompound(_derivative)) {
            uint256 rate = ICToken(_derivative).exchangeRateStored();
            address underlying = ICToken(_derivative).underlying();
            uint256 underlyingDecimals = ERC20(underlying).decimals();
            uint256 mantissa = 18 + underlyingDecimals - 8;
            uint256 oneCTokenInUnderlying = rate.mul(1e18).div(10**mantissa);
            return (underlying, _amount.mul(oneCTokenInUnderlying).div(1e8));
        }

        // YearnCRV just or CRV return USDC
        if (_isCRV(_derivative) || _isYearnCRV(_derivative)) {
            return (USDC, calcUSDCEquilavent(_derivative, _amount));
        }

        if (_isYearn(_derivative)) {
            _amount = _amount.mul(IYearn(_derivative).pricePerShare()).div(1e18);

            if (_derivative == yDAI) {
                return (DAI, _amount);
            }

            if (_derivative == yUSDC) {
                return (USDC, _amount);
            }

            if (_derivative == yUSDT) {
                return (USDT, _amount);
            }

            if (_derivative == yTUSD) {
                return (TUSD, _amount);
            }

            if (_derivative == ySUSD) {
                return (SUSD, _amount);
            }
        }

        return (_derivative, _amount);
    }

    // **** Stateful functions ****

    function zapToBMI(
        address _from,
        uint256 _amount,
        address _fromUnderlying,
        uint256 _fromUnderlyingAmount,
        uint256 _minBMIRecv,
        address[] memory _bmiConstituents,
        uint256[] memory _bmiConstituentsWeightings,
        address _aggregator,
        bytes memory _aggregatorData,
        bool refundDust
    ) public returns (uint256) {
        uint256 sum = 0;
        for (uint256 i = 0; i < _bmiConstituentsWeightings.length; i++) {
            sum = sum.add(_bmiConstituentsWeightings[i]);
        }

        // Sum should be between 0.999 and 1.000
        assert(sum <= 1e18);
        assert(sum >= 999e15);

        // Transfer to contract
        IERC20(_from).safeTransferFrom(msg.sender, address(this), _amount);

        // Primitive
        if (_isBare(_from)) {
            _primitiveToBMI(_from, _amount, _bmiConstituents, _bmiConstituentsWeightings, _aggregator, _aggregatorData);
        }
        // Yearn (primitive)
        else if (_isYearn(_from)) {
            IYearn(_from).withdraw();
            _primitiveToBMI(
                _fromUnderlying,
                _fromUnderlyingAmount,
                _bmiConstituents,
                _bmiConstituentsWeightings,
                _aggregator,
                _aggregatorData
            );
        }
        // Yearn (primitive)
        else if (_isYearnCRV(_from)) {
            IYearn(_from).withdraw();
            address crvToken = IYearn(_from).token();
            _crvToPrimitive(crvToken, IERC20(crvToken).balanceOf(address(this)));
            _primitiveToBMI(
                USDC,
                IERC20(USDC).balanceOf(address(this)),
                _bmiConstituents,
                _bmiConstituentsWeightings,
                address(0),
                ""
            );
        }
        // Compound
        else if (_isCompound(_from)) {
            require(ICToken(_from).redeem(_amount) == 0, "!ctoken-redeem");
            _primitiveToBMI(
                _fromUnderlying,
                _fromUnderlyingAmount,
                _bmiConstituents,
                _bmiConstituentsWeightings,
                _aggregator,
                _aggregatorData
            );
        }
        // Aave
        else if (_isAave(_from)) {
            IERC20(_from).safeApprove(AAVE_LENDING_POOL_V2, 0);
            IERC20(_from).safeApprove(AAVE_LENDING_POOL_V2, _amount);
            ILendingPoolV2(AAVE_LENDING_POOL_V2).withdraw(_fromUnderlying, type(uint256).max, address(this));

            _primitiveToBMI(
                _fromUnderlying,
                _fromUnderlyingAmount,
                _bmiConstituents,
                _bmiConstituentsWeightings,
                _aggregator,
                _aggregatorData
            );
        }
        // Curve
        else {
            _crvToPrimitive(_from, _amount);
            _primitiveToBMI(
                USDC,
                IERC20(USDC).balanceOf(address(this)),
                _bmiConstituents,
                _bmiConstituentsWeightings,
                address(0),
                ""
            );
        }

        // Checks
        uint256 _bmiBal = IERC20(BMI).balanceOf(address(this));
        require(_bmiBal >= _minBMIRecv, "!min-mint");
        IERC20(BMI).safeTransfer(msg.sender, _bmiBal);

        // Convert back dust to USDC and refund remaining USDC to usd
        if (refundDust) {
            for (uint256 i = 0; i < _bmiConstituents.length; i++) {
                _fromBMIConstituentToUSDC(_bmiConstituents[i], IERC20(_bmiConstituents[i]).balanceOf(address(this)));
            }
            IERC20(USDC).safeTransfer(msg.sender, IERC20(USDC).balanceOf(address(this)));
        }

        return _bmiBal;
    }

    // **** Internal helpers ****

    function _crvToPrimitive(address _from, uint256 _amount) internal {
        // Remove via zap to USDC
        if (_from == crvY || _from == crvSUSD || _from == crvYBUSD) {
            address zap = crvYZap;

            if (_from == crvSUSD) {
                zap = crvSUSDZap;
            } else if (_from == crvYBUSD) {
                zap = crvYBUSDZap;
            }

            IERC20(_from).safeApprove(zap, 0);
            IERC20(_from).safeApprove(zap, _amount);
            ICurveZapSimple(zap).remove_liquidity_one_coin(_amount, 1, 0, false);
        } else if (_from == crvUSDP || _from == crvUSDN || _from == crvDUSD || _from == crvMUSD || _from == crvUST) {
            address zap = crvUSDNZap;

            if (_from == crvUSDP) {
                zap = crvUSDPZap;
            } else if (_from == crvDUSD) {
                zap = crvDUSDZap;
            } else if (_from == crvMUSD) {
                zap = crvMUSDZap;
            } else if (_from == crvUST) {
                zap = crvUSTZap;
            }

            IERC20(_from).safeApprove(zap, 0);
            IERC20(_from).safeApprove(zap, _amount);
            ICurveZapSimple(zap).remove_liquidity_one_coin(_amount, 2, 0);
        } else if (_from == crvIB) {
            IERC20(_from).safeApprove(crvIBPool, 0);
            IERC20(_from).safeApprove(crvIBPool, _amount);
            ICurveZapSimple(crvIBPool).remove_liquidity_one_coin(_amount, 1, 0, true);
        } else if (_from == crvThree) {
            address zap = crvThreePool;

            IERC20(_from).safeApprove(zap, 0);
            IERC20(_from).safeApprove(zap, _amount);
            ICurveZapSimple(zap).remove_liquidity_one_coin(_amount, 1, 0);
        } else {
            // Meta pools, USDC is 2nd index
            IERC20(_from).safeApprove(crvMetaZapper, 0);
            IERC20(_from).safeApprove(crvMetaZapper, _amount);
            ICurveZapSimple(crvMetaZapper).remove_liquidity_one_coin(_from, _amount, 2, 0, address(this));
        }
    }

    function _primitiveToBMI(
        address _token,
        uint256 _amount,
        address[] memory _bmiConstituents,
        uint256[] memory _bmiConstituentsWeightings,
        address _aggregator,
        bytes memory _aggregatorData
    ) internal {
        // Offset, DAI = 0, USDC = 1, USDT = 2
        uint256 offset = 0;

        // Primitive to USDC (if not already USDC)
        if (_token != DAI && _token != USDC && _token != USDT) {
            IERC20(_token).safeApprove(_aggregator, 0);
            IERC20(_token).safeApprove(_aggregator, _amount);

            (bool success, ) = _aggregator.call(_aggregatorData);
            require(success, "!swap");

            // Always goes to USDC
            // If we swapping
            _token = USDC;
        }

        if (_token == USDC) {
            offset = 1;
        } else if (_token == USDT) {
            offset = 2;
        }

        // Amount to mint
        uint256 amountToMint;
        uint256 bmiSupply = IERC20(BMI).totalSupply();

        uint256 tokenBal = IERC20(_token).balanceOf(address(this));
        uint256 tokenAmount;
        for (uint256 i = 0; i < _bmiConstituents.length; i++) {
            // Weighting of the token for BMI constituient
            tokenAmount = tokenBal.mul(_bmiConstituentsWeightings[i]).div(1e18);
            _toBMIConstituent(_token, _bmiConstituents[i], tokenAmount, offset);

            // Get amount to Mint
            amountToMint = _approveBMIAndGetMintableAmount(bmiSupply, _bmiConstituents[i], amountToMint);
        }

        // Mint BASK
        IBasket(BMI).mint(amountToMint);
    }

    function _approveBMIAndGetMintableAmount(
        uint256 _bmiTotalSupply,
        address _bmiConstituient,
        uint256 _curMintAmount
    ) internal returns (uint256) {
        uint256 bal = IERC20(_bmiConstituient).balanceOf(address(this));
        uint256 bmiBal = IERC20(_bmiConstituient).balanceOf(BMI);

        IERC20(_bmiConstituient).safeApprove(BMI, 0);
        IERC20(_bmiConstituient).safeApprove(BMI, bal);

        // Calculate how much BMI we can mint at max
        // Formula: min(e for e in bmiSupply * tokenWeHave[e] / tokenInBMI[e])
        if (_curMintAmount == 0) {
            return _bmiTotalSupply.mul(bal).div(bmiBal);
        }

        uint256 temp = _bmiTotalSupply.mul(bal).div(bmiBal);
        if (temp < _curMintAmount) {
            return temp;
        }

        return _curMintAmount;
    }

    function _toBMIConstituent(
        address _fromToken,
        address _toToken,
        uint256 _amount,
        uint256 _curveOffset
    ) internal {
        uint256 bal;
        uint256[4] memory depositAmounts4 = [uint256(0), uint256(0), uint256(0), uint256(0)];

        if (_toToken == ySUSD) {
            IERC20(_fromToken).safeApprove(crvSUSDPool, 0);
            IERC20(_fromToken).safeApprove(crvSUSDPool, _amount);

            ICurvePool(crvSUSDPool).exchange(int128(_curveOffset), 3, _amount, 0);

            bal = IERC20(SUSD).balanceOf(address(this));
            IERC20(SUSD).safeApprove(ySUSD, 0);
            IERC20(SUSD).safeApprove(ySUSD, bal);
        }
        // Gen 1 pools
        else if (
            _toToken == yCRV ||
            _toToken == ycrvSUSD ||
            _toToken == ycrvYBUSD ||
            _toToken == ycrvUSDN ||
            _toToken == ycrvUSDP ||
            _toToken == ycrvDUSD ||
            _toToken == ycrvMUSD ||
            _toToken == ycrvUST
        ) {
            address crvToken = IYearn(_toToken).token();

            address zap = crvYZap;
            if (_toToken == ycrvSUSD) {
                zap = crvSUSDZap;
            } else if (_toToken == ycrvYBUSD) {
                zap = crvYBUSDZap;
            } else if (_toToken == ycrvUSDN) {
                zap = crvUSDNZap;
                _curveOffset += 1;
            } else if (_toToken == ycrvUSDP) {
                zap = crvUSDPZap;
                _curveOffset += 1;
            } else if (_toToken == ycrvDUSD) {
                zap = crvDUSDZap;
                _curveOffset += 1;
            } else if (_toToken == ycrvMUSD) {
                zap = crvMUSDZap;
                _curveOffset += 1;
            } else if (_toToken == ycrvUST) {
                zap = crvUSTZap;
                _curveOffset += 1;
            }

            depositAmounts4[_curveOffset] = _amount;
            IERC20(_fromToken).safeApprove(zap, 0);
            IERC20(_fromToken).safeApprove(zap, _amount);
            ICurveZapSimple(zap).add_liquidity(depositAmounts4, 0);

            bal = IERC20(crvToken).balanceOf(address(this));
            IERC20(crvToken).safeApprove(_toToken, 0);
            IERC20(crvToken).safeApprove(_toToken, bal);
        } else if (_toToken == ycrvThree || _toToken == ycrvIB) {
            address crvToken = IYearn(_toToken).token();

            uint256[3] memory depositAmounts3 = [uint256(0), uint256(0), uint256(0)];
            depositAmounts3[_curveOffset] = _amount;

            address zap = crvThreePool;
            if (_toToken == ycrvIB) {
                zap = crvIBPool;
            }

            IERC20(_fromToken).safeApprove(zap, 0);
            IERC20(_fromToken).safeApprove(zap, _amount);

            if (_toToken == ycrvThree) {
                ICurveZapSimple(zap).add_liquidity(depositAmounts3, 0);
            } else {
                ICurveZapSimple(zap).add_liquidity(depositAmounts3, 0, true);
            }

            bal = IERC20(crvToken).balanceOf(address(this));
            IERC20(crvToken).safeApprove(_toToken, 0);
            IERC20(crvToken).safeApprove(_toToken, bal);
        }
        // Meta pools
        else if (_toToken == ycrvBUSD || _toToken == ycrvFRAX || _toToken == ycrvALUSD || _toToken == ycrvLUSD) {
            // CRV Token = CRV Pool
            address crvToken = IYearn(_toToken).token();

            depositAmounts4[_curveOffset + 1] = _amount;
            IERC20(_fromToken).safeApprove(crvMetaZapper, 0);
            IERC20(_fromToken).safeApprove(crvMetaZapper, _amount);

            ICurveZapSimple(crvMetaZapper).add_liquidity(crvToken, depositAmounts4, 0);

            bal = IERC20(crvToken).balanceOf(address(this));
            IERC20(crvToken).safeApprove(_toToken, 0);
            IERC20(crvToken).safeApprove(_toToken, bal);
        }

        IYearn(_toToken).deposit();
    }

    function _fromBMIConstituentToUSDC(address _fromToken, uint256 _amount) internal {
        if (_isYearnCRV(_fromToken)) {
            _crvToPrimitive(IYearn(_fromToken).token(), IYearn(_fromToken).withdraw(_amount));
        }
    }

    function _isBare(address _token) internal pure returns (bool) {
        return (_token == DAI ||
            _token == USDC ||
            _token == USDT ||
            _token == TUSD ||
            _token == SUSD ||
            _token == BUSD ||
            _token == USDP ||
            _token == FRAX ||
            _token == ALUSD ||
            _token == LUSD ||
            _token == USDN);
    }

    function _isYearn(address _token) internal pure returns (bool) {
        return (_token == yDAI || _token == yUSDC || _token == yUSDT || _token == yTUSD || _token == ySUSD);
    }

    function _isYearnCRV(address _token) internal pure returns (bool) {
        return (_token == yCRV ||
            _token == ycrvSUSD ||
            _token == ycrvYBUSD ||
            _token == ycrvBUSD ||
            _token == ycrvUSDP ||
            _token == ycrvFRAX ||
            _token == ycrvALUSD ||
            _token == ycrvLUSD ||
            _token == ycrvUSDN ||
            _token == ycrvThree ||
            _token == ycrvIB ||
            _token == ycrvMUSD ||
            _token == ycrvUST ||
            _token == ycrvDUSD);
    }

    function _isCRV(address _token) internal pure returns (bool) {
        return (_token == crvY ||
            _token == crvSUSD ||
            _token == crvYBUSD ||
            _token == crvBUSD ||
            _token == crvUSDP ||
            _token == crvFRAX ||
            _token == crvALUSD ||
            _token == crvLUSD ||
            _token == crvThree ||
            _token == crvUSDN ||
            _token == crvDUSD ||
            _token == crvMUSD ||
            _token == crvUST ||
            _token == crvIB);
    }

    function _isCompound(address _token) internal pure returns (bool) {
        return (_token == cDAI || _token == cUSDC || _token == cUSDT || _token == cTUSD);
    }

    function _isAave(address _token) internal pure returns (bool) {
        return (_token == aDAI || _token == aUSDC || _token == aUSDT || _token == aTUSD || _token == aSUSD);
    }
}

File 5 of 17: Context.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

File 6 of 17: ERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./Context.sol";
import "./IERC20.sol";
import "./SafeMath.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20 {
    using SafeMath for uint256;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;
    uint8 private _decimals;

    /**
     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with
     * a default value of 18.
     *
     * To select a different value for {decimals}, use {_setupDecimals}.
     *
     * All three of these values are immutable: they can only be set once during
     * construction.
     */
    constructor (string memory name_, string memory symbol_) public {
        _name = name_;
        _symbol = symbol_;
        _decimals = 18;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5,05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
     * called.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual returns (uint8) {
        return _decimals;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * Requirements:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Sets {decimals} to a value other than the default one of 18.
     *
     * WARNING: This function should only be called from the constructor. Most
     * applications that interact with token contracts will not expect
     * {decimals} to ever change, and may work incorrectly if it does.
     */
    function _setupDecimals(uint8 decimals_) internal virtual {
        _decimals = decimals_;
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be to transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}

File 7 of 17: IATokenV2.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

interface IATokenV2 {
    function ATOKEN_REVISION() external view returns (uint256);

    function DOMAIN_SEPARATOR() external view returns (bytes32);

    function EIP712_REVISION() external view returns (bytes memory);

    function PERMIT_TYPEHASH() external view returns (bytes32);

    function POOL() external view returns (address);

    function RESERVE_TREASURY_ADDRESS() external view returns (address);

    function UINT_MAX_VALUE() external view returns (uint256);

    function UNDERLYING_ASSET_ADDRESS() external view returns (address);

    function _nonces(address) external view returns (uint256);

    function allowance(address owner, address spender) external view returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);

    function balanceOf(address user) external view returns (uint256);

    function burn(
        address user,
        address receiverOfUnderlying,
        uint256 amount,
        uint256 index
    ) external;

    function decimals() external view returns (uint8);

    function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);

    function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256);

    function increaseAllowance(address spender, uint256 addedValue) external returns (bool);

    function initialize(
        uint8 underlyingAssetDecimals,
        string memory tokenName,
        string memory tokenSymbol
    ) external;

    function mint(
        address user,
        uint256 amount,
        uint256 index
    ) external returns (bool);

    function mintToTreasury(uint256 amount, uint256 index) external;

    function name() external view returns (string memory);

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

    function scaledBalanceOf(address user) external view returns (uint256);

    function scaledTotalSupply() external view returns (uint256);

    function symbol() external view returns (string memory);

    function totalSupply() external view returns (uint256);

    function transfer(address recipient, uint256 amount) external returns (bool);

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    function transferOnLiquidation(
        address from,
        address to,
        uint256 value
    ) external;

    function transferUnderlyingTo(address target, uint256 amount) external returns (uint256);
}

File 8 of 17: IBasket.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

interface IBasket {
    function transfer(address dst, uint256 amount) external returns (bool);

    function totalSupply() external view returns (uint256);

    function mint(uint256) external;

    function getOne() external view returns (address[] memory, uint256[] memory);

    function getAssetsAndBalances() external view returns (address[] memory, uint256[] memory);

    function burn(uint256) external;

    function viewMint(uint256 _amountOut) external view returns (uint256[] memory _amountsIn);
}

File 9 of 17: ICToken.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

interface ICToken {
    function _acceptAdmin() external returns (uint256);

    function _addReserves(uint256 addAmount) external returns (uint256);

    function _reduceReserves(uint256 reduceAmount) external returns (uint256);

    function _setComptroller(address newComptroller) external returns (uint256);

    function _setImplementation(
        address implementation_,
        bool allowResign,
        bytes memory becomeImplementationData
    ) external;

    function _setInterestRateModel(address newInterestRateModel) external returns (uint256);

    function _setPendingAdmin(address newPendingAdmin) external returns (uint256);

    function _setReserveFactor(uint256 newReserveFactorMantissa) external returns (uint256);

    function accrualBlockNumber() external view returns (uint256);

    function accrueInterest() external returns (uint256);

    function admin() external view returns (address);

    function allowance(address owner, address spender) external view returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);

    function balanceOf(address owner) external view returns (uint256);

    function balanceOfUnderlying(address owner) external returns (uint256);

    function borrow(uint256 borrowAmount) external returns (uint256);

    function borrowBalanceCurrent(address account) external returns (uint256);

    function borrowBalanceStored(address account) external view returns (uint256);

    function borrowIndex() external view returns (uint256);

    function borrowRatePerBlock() external view returns (uint256);

    function comptroller() external view returns (address);

    function decimals() external view returns (uint8);

    function delegateToImplementation(bytes memory data) external returns (bytes memory);

    function delegateToViewImplementation(bytes memory data) external view returns (bytes memory);

    function exchangeRateCurrent() external returns (uint256);

    function exchangeRateStored() external view returns (uint256);

    function getAccountSnapshot(address account)
        external
        view
        returns (
            uint256,
            uint256,
            uint256,
            uint256
        );

    function getCash() external view returns (uint256);

    function implementation() external view returns (address);

    function interestRateModel() external view returns (address);

    function isCToken() external view returns (bool);

    function liquidateBorrow(
        address borrower,
        uint256 repayAmount,
        address cTokenCollateral
    ) external returns (uint256);

    function mint(uint256 mintAmount) external returns (uint256);

    function name() external view returns (string memory);

    function pendingAdmin() external view returns (address);

    function redeem(uint256 redeemTokens) external returns (uint256);

    function redeemUnderlying(uint256 redeemAmount) external returns (uint256);

    function repayBorrow(uint256 repayAmount) external returns (uint256);

    function repayBorrowBehalf(address borrower, uint256 repayAmount) external returns (uint256);

    function reserveFactorMantissa() external view returns (uint256);

    function seize(
        address liquidator,
        address borrower,
        uint256 seizeTokens
    ) external returns (uint256);

    function supplyRatePerBlock() external view returns (uint256);

    function symbol() external view returns (string memory);

    function totalBorrows() external view returns (uint256);

    function totalBorrowsCurrent() external returns (uint256);

    function totalReserves() external view returns (uint256);

    function totalSupply() external view returns (uint256);

    function transfer(address dst, uint256 amount) external returns (bool);

    function transferFrom(
        address src,
        address dst,
        uint256 amount
    ) external returns (bool);

    function underlying() external view returns (address);
}

File 10 of 17: ICurve.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

interface ICurvePool {
    function exchange(
        int128 i,
        int128 j,
        uint256 _dx,
        uint256 _min_dy
    ) external;

    function get_dy(
        int128 i,
        int128 j,
        uint256 _dx
    ) external view returns (uint256);

    function get_virtual_price() external view returns (uint256);
}

interface ICurveLINK {
    function A() external view returns (uint256);

    function A_precise() external view returns (uint256);

    function get_virtual_price() external view returns (uint256);

    function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit) external view returns (uint256);

    function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount) external returns (uint256);

    function get_dy(
        int128 i,
        int128 j,
        uint256 _dx
    ) external view returns (uint256);

    function exchange(
        int128 i,
        int128 j,
        uint256 _dx,
        uint256 _min_dy
    ) external returns (uint256);

    function remove_liquidity(uint256 _amount, uint256[2] memory _min_amounts) external returns (uint256[2] memory);

    function remove_liquidity_imbalance(uint256[2] memory _amounts, uint256 _max_burn_amount)
        external
        returns (uint256);

    function calc_withdraw_one_coin(uint256 _token_amount, int128 i) external view returns (uint256);

    function remove_liquidity_one_coin(
        uint256 _token_amount,
        int128 i,
        uint256 _min_amount
    ) external returns (uint256);

    function ramp_A(uint256 _future_A, uint256 _future_time) external;

    function stop_ramp_A() external;

    function commit_new_fee(uint256 _new_fee, uint256 _new_admin_fee) external;

    function apply_new_fee() external;

    function revert_new_parameters() external;

    function commit_transfer_ownership(address _owner) external;

    function apply_transfer_ownership() external;

    function revert_transfer_ownership() external;

    function admin_balances(uint256 i) external view returns (uint256);

    function withdraw_admin_fees() external;

    function donate_admin_fees() external;

    function kill_me() external;

    function unkill_me() external;

    function coins(uint256 arg0) external view returns (address);

    function balances(uint256 arg0) external view returns (uint256);

    function fee() external view returns (uint256);

    function admin_fee() external view returns (uint256);

    function previous_balances(uint256 arg0) external view returns (uint256);

    function block_timestamp_last() external view returns (uint256);

    function owner() external view returns (address);

    function lp_token() external view returns (address);

    function initial_A() external view returns (uint256);

    function future_A() external view returns (uint256);

    function initial_A_time() external view returns (uint256);

    function future_A_time() external view returns (uint256);

    function admin_actions_deadline() external view returns (uint256);

    function transfer_ownership_deadline() external view returns (uint256);

    function future_fee() external view returns (uint256);

    function future_admin_fee() external view returns (uint256);

    function future_owner() external view returns (address);
}

interface ILinkGauge {
    function decimals() external view returns (uint256);

    function integrate_checkpoint() external view returns (uint256);

    function user_checkpoint(address addr) external returns (bool);

    function claimable_tokens(address addr) external returns (uint256);

    function claimable_reward(address _addr, address _token) external returns (uint256);

    function claim_rewards() external;

    function claim_rewards(address _addr) external;

    function claim_historic_rewards(address[8] memory _reward_tokens) external;

    function claim_historic_rewards(address[8] memory _reward_tokens, address _addr) external;

    function kick(address addr) external;

    function set_approve_deposit(address addr, bool can_deposit) external;

    function deposit(uint256 _value) external;

    function deposit(uint256 _value, address _addr) external;

    function withdraw(uint256 _value) external;

    function allowance(address _owner, address _spender) external view returns (uint256);

    function transfer(address _to, uint256 _value) external returns (bool);

    function transferFrom(
        address _from,
        address _to,
        uint256 _value
    ) external returns (bool);

    function approve(address _spender, uint256 _value) external returns (bool);

    function increaseAllowance(address _spender, uint256 _added_value) external returns (bool);

    function decreaseAllowance(address _spender, uint256 _subtracted_value) external returns (bool);

    function set_rewards(
        address _reward_contract,
        bytes32 _sigs,
        address[8] memory _reward_tokens
    ) external;

    function set_killed(bool _is_killed) external;

    function commit_transfer_ownership(address addr) external;

    function accept_transfer_ownership() external;

    function minter() external view returns (address);

    function crv_token() external view returns (address);

    function lp_token() external view returns (address);

    function controller() external view returns (address);

    function voting_escrow() external view returns (address);

    function future_epoch_time() external view returns (uint256);

    function balanceOf(address arg0) external view returns (uint256);

    function totalSupply() external view returns (uint256);

    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function approved_to_deposit(address arg0, address arg1) external view returns (bool);

    function working_balances(address arg0) external view returns (uint256);

    function working_supply() external view returns (uint256);

    function period() external view returns (int128);

    function period_timestamp(uint256 arg0) external view returns (uint256);

    function integrate_inv_supply(uint256 arg0) external view returns (uint256);

    function integrate_inv_supply_of(address arg0) external view returns (uint256);

    function integrate_checkpoint_of(address arg0) external view returns (uint256);

    function integrate_fraction(address arg0) external view returns (uint256);

    function inflation_rate() external view returns (uint256);

    function reward_contract() external view returns (address);

    function reward_tokens(uint256 arg0) external view returns (address);

    function reward_integral(address arg0) external view returns (uint256);

    function reward_integral_for(address arg0, address arg1) external view returns (uint256);

    function admin() external view returns (address);

    function future_admin() external view returns (address);

    function is_killed() external view returns (bool);
}

File 11 of 17: ICurveZap.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

interface ICurveZapSimple {
    function add_liquidity(uint256[3] memory _deposit_amounts, uint256 _min_mint_amount) external;

    function add_liquidity(
        uint256[3] memory _deposit_amounts,
        uint256 _min_mint_amount,
        bool use_underlying
    ) external;

    function add_liquidity(uint256[4] memory _deposit_amounts, uint256 _min_mint_amount) external;

    function add_liquidity(
        address _pool,
        uint256[4] memory _deposit_amounts,
        uint256 _min_mint_amount
    ) external returns (uint256);

    function add_liquidity(
        address _pool,
        uint256[4] memory _deposit_amounts,
        uint256 _min_mint_amount,
        address _receiver
    ) external returns (uint256);

    function remove_liquidity_one_coin(
        uint256 _token_amount,
        int128 i,
        uint256 min_amount,
        bool _donate_dust
    ) external;

    function remove_liquidity_one_coin(
        uint256 _token_amount,
        int128 i,
        uint256 min_amount
    ) external;

    function remove_liquidity_one_coin(
        address pool,
        uint256 _token_amount,
        int128 i,
        uint256 min_amount,
        address _receiver
    ) external returns (uint256);

    function remove_liquidity_one_coin(
        uint256 _token_amount,
        int128 i,
        uint256 min_amount,
        address _receiver
    ) external returns (uint256);

    function calc_withdraw_one_coin(uint256 _token_amount, int128 i) external view returns (uint256);

    function calc_withdraw_one_coin(
        uint256 _token_amount,
        int128 i,
        bool use_underlying
    ) external view returns (uint256);

    function calc_withdraw_one_coin(
        address pool,
        uint256 _token_amount,
        int128 i
    ) external view returns (uint256);
}

File 12 of 17: IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

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

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

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

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

File 13 of 17: ILendingPoolV2.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

interface ILendingPoolV2 {
    function FLASHLOAN_PREMIUM_TOTAL() external view returns (uint256);

    function LENDINGPOOL_REVISION() external view returns (uint256);

    function MAX_NUMBER_RESERVES() external view returns (uint256);

    function MAX_STABLE_RATE_BORROW_SIZE_PERCENT() external view returns (uint256);

    function borrow(
        address asset,
        uint256 amount,
        uint256 interestRateMode,
        uint16 referralCode,
        address onBehalfOf
    ) external;

    function deposit(
        address asset,
        uint256 amount,
        address onBehalfOf,
        uint16 referralCode
    ) external;

    function finalizeTransfer(
        address asset,
        address from,
        address to,
        uint256 amount,
        uint256 balanceFromBefore,
        uint256 balanceToBefore
    ) external;

    function flashLoan(
        address receiverAddress,
        address[] memory assets,
        uint256[] memory amounts,
        uint256[] memory modes,
        address onBehalfOf,
        bytes memory params,
        uint16 referralCode
    ) external;

    function getAddressesProvider() external view returns (address);

    function getConfiguration(address asset) external view returns (uint256);

    function getReserveData(address asset)
        external
        view
        returns (
            uint256,
            uint128,
            uint128,
            uint128,
            uint128,
            uint128,
            uint40,
            address,
            address,
            address,
            address,
            uint8
        );

    function getReserveNormalizedIncome(address asset) external view returns (uint256);

    function getReserveNormalizedVariableDebt(address asset) external view returns (uint256);

    function getReservesList() external view returns (address[] memory);

    function getUserAccountData(address user)
        external
        view
        returns (
            uint256 totalCollateralETH,
            uint256 totalDebtETH,
            uint256 availableBorrowsETH,
            uint256 currentLiquidationThreshold,
            uint256 ltv,
            uint256 healthFactor
        );

    function initReserve(
        address asset,
        address aTokenAddress,
        address stableDebtAddress,
        address variableDebtAddress,
        address interestRateStrategyAddress
    ) external;

    function initialize(address provider) external;

    function liquidationCall(
        address collateralAsset,
        address debtAsset,
        address user,
        uint256 debtToCover,
        bool receiveAToken
    ) external;

    function paused() external view returns (bool);

    function rebalanceStableBorrowRate(address asset, address user) external;

    function repay(
        address asset,
        uint256 amount,
        uint256 rateMode,
        address onBehalfOf
    ) external returns (uint256);

    function setConfiguration(address asset, uint256 configuration) external;

    function setPause(bool val) external;

    function setReserveInterestRateStrategyAddress(address asset, address rateStrategyAddress) external;

    function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external;

    function swapBorrowRateMode(address asset, uint256 rateMode) external;

    function withdraw(
        address asset,
        uint256 amount,
        address to
    ) external returns (uint256);
}

File 14 of 17: IYearn.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

interface IYearn {
    function initialize(
        address token,
        address governance,
        address rewards,
        string memory nameOverride,
        string memory symbolOverride
    ) external;

    function initialize(
        address token,
        address governance,
        address rewards,
        string memory nameOverride,
        string memory symbolOverride,
        address guardian
    ) external;

    function apiVersion() external pure returns (string memory);

    function setName(string memory name) external;

    function setSymbol(string memory symbol) external;

    function setGovernance(address governance) external;

    function acceptGovernance() external;

    function setManagement(address management) external;

    function setGuestList(address guestList) external;

    function setRewards(address rewards) external;

    function setLockedProfitDegration(uint256 degration) external;

    function setDepositLimit(uint256 limit) external;

    function setPerformanceFee(uint256 fee) external;

    function setManagementFee(uint256 fee) external;

    function setGuardian(address guardian) external;

    function setEmergencyShutdown(bool active) external;

    function setWithdrawalQueue(address[20] memory queue) external;

    function transfer(address receiver, uint256 amount) external returns (bool);

    function transferFrom(
        address sender,
        address receiver,
        uint256 amount
    ) external returns (bool);

    function approve(address spender, uint256 amount) external returns (bool);

    function increaseAllowance(address spender, uint256 amount) external returns (bool);

    function decreaseAllowance(address spender, uint256 amount) external returns (bool);

    function permit(
        address owner,
        address spender,
        uint256 amount,
        uint256 expiry,
        bytes memory signature
    ) external returns (bool);

    function totalAssets() external view returns (uint256);

    function deposit() external returns (uint256);

    function deposit(uint256 _amount) external returns (uint256);

    function deposit(uint256 _amount, address recipient) external returns (uint256);

    function maxAvailableShares() external view returns (uint256);

    function withdraw() external returns (uint256);

    function withdraw(uint256 maxShares) external returns (uint256);

    function withdraw(uint256 maxShares, address recipient) external returns (uint256);

    function withdraw(
        uint256 maxShares,
        address recipient,
        uint256 maxLoss
    ) external returns (uint256);

    function pricePerShare() external view returns (uint256);

    function addStrategy(
        address strategy,
        uint256 debtRatio,
        uint256 minDebtPerHarvest,
        uint256 maxDebtPerHarvest,
        uint256 performanceFee
    ) external;

    function updateStrategyDebtRatio(address strategy, uint256 debtRatio) external;

    function updateStrategyMinDebtPerHarvest(address strategy, uint256 minDebtPerHarvest) external;

    function updateStrategyMaxDebtPerHarvest(address strategy, uint256 maxDebtPerHarvest) external;

    function updateStrategyPerformanceFee(address strategy, uint256 performanceFee) external;

    function migrateStrategy(address oldVersion, address newVersion) external;

    function revokeStrategy() external;

    function revokeStrategy(address strategy) external;

    function addStrategyToQueue(address strategy) external;

    function removeStrategyFromQueue(address strategy) external;

    function debtOutstanding() external view returns (uint256);

    function debtOutstanding(address strategy) external view returns (uint256);

    function creditAvailable() external view returns (uint256);

    function creditAvailable(address strategy) external view returns (uint256);

    function availableDepositLimit() external view returns (uint256);

    function expectedReturn() external view returns (uint256);

    function expectedReturn(address strategy) external view returns (uint256);

    function report(
        uint256 gain,
        uint256 loss,
        uint256 _debtPayment
    ) external returns (uint256);

    function sweep(address token) external;

    function sweep(address token, uint256 amount) external;

    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function decimals() external view returns (uint256);

    function precisionFactor() external view returns (uint256);

    function balanceOf(address arg0) external view returns (uint256);

    function allowance(address arg0, address arg1) external view returns (uint256);

    function totalSupply() external view returns (uint256);

    function token() external view returns (address);

    function governance() external view returns (address);

    function management() external view returns (address);

    function guardian() external view returns (address);

    function guestList() external view returns (address);

    function strategies(address arg0)
        external
        view
        returns (
            uint256 performanceFee,
            uint256 activation,
            uint256 debtRatio,
            uint256 minDebtPerHarvest,
            uint256 maxDebtPerHarvest,
            uint256 lastReport,
            uint256 totalDebt,
            uint256 totalGain,
            uint256 totalLoss
        );

    function withdrawalQueue(uint256 arg0) external view returns (address);

    function emergencyShutdown() external view returns (bool);

    function depositLimit() external view returns (uint256);

    function debtRatio() external view returns (uint256);

    function totalDebt() external view returns (uint256);

    function lastReport() external view returns (uint256);

    function activation() external view returns (uint256);

    function lockedProfit() external view returns (uint256);

    function lockedProfitDegration() external view returns (uint256);

    function rewards() external view returns (address);

    function managementFee() external view returns (uint256);

    function performanceFee() external view returns (uint256);

    function nonces(address arg0) external view returns (uint256);

    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

File 15 of 17: Ownable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./Context.sol";
/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor () internal {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

File 16 of 17: SafeERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./IERC20.sol";
import "./SafeMath.sol";
import "./Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using SafeMath for uint256;
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 17 of 17: SafeMath.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) return (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) return 0;
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a % b;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minRecv","type":"uint256"}],"name":"burnBMIToUSDC","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"calcUSDCEquilavent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_derivative","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"getUnderlyingAmount","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"}],"name":"recoverERC20s","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_fromUnderlying","type":"address"},{"internalType":"uint256","name":"_fromUnderlyingAmount","type":"uint256"},{"internalType":"uint256","name":"_minBMIRecv","type":"uint256"},{"internalType":"address[]","name":"_bmiConstituents","type":"address[]"},{"internalType":"uint256[]","name":"_bmiConstituentsWeightings","type":"uint256[]"},{"internalType":"address","name":"_aggregator","type":"address"},{"internalType":"bytes","name":"_aggregatorData","type":"bytes"},{"internalType":"bool","name":"refundDust","type":"bool"}],"name":"zapToBMI","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b5060006200001e6200006e565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35062000072565b3390565b61470a80620000826000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c80638da5cb5b116100665780638da5cb5b146101525780639e8c708e14610176578063a063c0421461019c578063a7a580d514610383578063f2fde38b1461042457610093565b806331bceb48146100985780636331f17f146100d6578063715018a6146101255780637a991e121461012f575b600080fd5b6100c4600480360360408110156100ae57600080fd5b506001600160a01b03813516906020013561044a565b60408051918252519081900360200190f35b610102600480360360408110156100ec57600080fd5b506001600160a01b038135169060200135610a77565b604080516001600160a01b03909316835260208301919091528051918290030190f35b61012d610ec1565b005b6100c46004803603604081101561014557600080fd5b5080359060200135610f6d565b61015a611348565b604080516001600160a01b039092168252519081900360200190f35b61012d6004803603602081101561018c57600080fd5b50356001600160a01b0316611357565b6100c460048036036101408110156101b357600080fd5b6001600160a01b03823581169260208101359260408201359092169160608201359160808101359181019060c0810160a0820135600160201b8111156101f857600080fd5b82018360208201111561020a57600080fd5b803590602001918460208302840111600160201b8311171561022b57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561027a57600080fd5b82018360208201111561028c57600080fd5b803590602001918460208302840111600160201b831117156102ad57600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092956001600160a01b03853516959094909350604081019250602001359050600160201b81111561030d57600080fd5b82018360208201111561031f57600080fd5b803590602001918460018302840111600160201b8311171561034057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505050351515905061144a565b61012d6004803603602081101561039957600080fd5b810190602081018135600160201b8111156103b357600080fd5b8201836020820111156103c557600080fd5b803590602001918460208302840111600160201b831117156103e657600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611b81945050505050565b61012d6004803603602081101561043a57600080fd5b50356001600160a01b0316611cb9565b600061045583611dbb565b15610545576104db670de0b6b3a76400006104d5856001600160a01b03166399530b066040518163ffffffff1660e01b815260040160206040518083038186803b1580156104a257600080fd5b505afa1580156104b6573d6000803e3d6000fd5b505050506040513d60208110156104cc57600080fd5b50518590611fdd565b9061203d565b9150826001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561051657600080fd5b505afa15801561052a573d6000803e3d6000fd5b505050506040513d602081101561054057600080fd5b505192505b6001600160a01b03831673df5e0e81dff6faf3a7e52ba697820c5e32d806a8148061058c57506001600160a01b03831673c25a3a3b969415c80451098fa907ec722572917f145b806105b357506001600160a01b038316736c3f90f043a72fa612cbac8115ee7e52bde6e490145b806105da57506001600160a01b038316733b3ac5386837dc563660fb6a0937dfaa5924333b145b156107325773bbc81d23ea2c3ec7e56d39296f0cbb648873a5d36001600160a01b03841673c25a3a3b969415c80451098fa907ec722572917f1415610634575073fcba3e75865d2d561be8d220616520c171f128516106b0565b6001600160a01b038416736c3f90f043a72fa612cbac8115ee7e52bde6e4901415610674575073bebc44782c7db0a1a60cb6fe97d0b483032ff1c76106b0565b6001600160a01b038416733b3ac5386837dc563660fb6a0937dfaa5924333b14156106b0575073b6c057591e073249f2d9d88ba59a46cfc9b59edb5b806001600160a01b031663cc2b27d78460016040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156106fd57600080fd5b505afa158015610711573d6000803e3d6000fd5b505050506040513d602081101561072757600080fd5b50519150610a719050565b6001600160a01b038316734f3e8f405cf5afc05d68142f3783bdfe13811522148061077957506001600160a01b038316737eb40e450b9655f4b3cc4259bcc731c63ff55ae6145b806107a057506001600160a01b038316733a664ab939fd8482048609f652f9a0b0677337b9145b806107c757506001600160a01b038316731aef73d49dedc4b1778d0706583995958dc862e6145b806107ee57506001600160a01b0383167394e131324b6054c0d789b190b2dac504e4361b53145b156109515773094d12e5b541784701fd8d65f11fc0598fbc63326001600160a01b038416737eb40e450b9655f4b3cc4259bcc731c63ff55ae614156108485750733c8caee4e09296800f8d29a68fa3837e2dae4940610904565b6001600160a01b038416733a664ab939fd8482048609f652f9a0b0677337b9141561088857507361e10659fe3aa93d036d099405224e4ac24996d0610904565b6001600160a01b038416731aef73d49dedc4b1778d0706583995958dc862e614156108c8575073803a2b40c5a9bb2b86dd630b274fa2a9202874c2610904565b6001600160a01b0384167394e131324b6054c0d789b190b2dac504e4361b531415610904575073b0a0716841f2fc03fba72a891b8bb13584f52f2d5b806001600160a01b031663cc2b27d78460026040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156106fd57600080fd5b6001600160a01b038316735282a4ef67d9c33135340fb3289cc1711c13638c1415610a09576040805163314ca9dd60e21b81526004810184905260016024820181905260448201529051732dded6da1bf5dbdf597c45fcfaa3194e53ecfeaf9163c532a774916064808301926020929190829003018186803b1580156109d657600080fd5b505afa1580156109ea573d6000803e3d6000fd5b505050506040513d6020811015610a0057600080fd5b50519050610a71565b604080516341b028f360e01b81526001600160a01b03851660048201526024810184905260026044820152905173a79828df1850e8a3a3064576f380d90aecdd3359916341b028f3916064808301926020929190829003018186803b1580156109d657600080fd5b92915050565b600080610a83846120a4565b15610af757836001600160a01b031663b16a19de6040518163ffffffff1660e01b815260040160206040518083038186803b158015610ac157600080fd5b505afa158015610ad5573d6000803e3d6000fd5b505050506040513d6020811015610aeb57600080fd5b50519150829050610eba565b610b0084612164565b15610c9a576000846001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b158015610b4057600080fd5b505afa158015610b54573d6000803e3d6000fd5b505050506040513d6020811015610b6a57600080fd5b505160408051636f307dc360e01b815290519192506000916001600160a01b03881691636f307dc3916004808301926020929190829003018186803b158015610bb257600080fd5b505afa158015610bc6573d6000803e3d6000fd5b505050506040513d6020811015610bdc57600080fd5b50516040805163313ce56760e01b815290519192506000916001600160a01b0384169163313ce567916004808301926020929190829003018186803b158015610c2457600080fd5b505afa158015610c38573d6000803e3d6000fd5b505050506040513d6020811015610c4e57600080fd5b505160ff169050600a80820190600090610c779083900a6104d587670de0b6b3a7640000611fdd565b905083610c8c6305f5e1006104d58b85611fdd565b965096505050505050610eba565b610ca3846121fd565b80610cb25750610cb284611dbb565b15610cdf5773a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48610cd6858561044a565b91509150610eba565b610ce88461241c565b15610eb457610d68670de0b6b3a76400006104d5866001600160a01b03166399530b066040518163ffffffff1660e01b815260040160206040518083038186803b158015610d3557600080fd5b505afa158015610d49573d6000803e3d6000fd5b505050506040513d6020811015610d5f57600080fd5b50518690611fdd565b92506001600160a01b0384167319d3364a399d251e894ac732651be8b0e4e850011415610dad5750736b175474e89094c44da98b954eedeac495271d0f905081610eba565b6001600160a01b038416735f18c75abdae578b483e5f43f12a39cf75b973a91415610df0575073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48905081610eba565b6001600160a01b038416737da96a3891add058ada2e826306d812c638d87a71415610e33575073dac17f958d2ee523a2206206994597c13d831ec7905081610eba565b6001600160a01b0384167337d19d1c4e1fa9dc47bd1ea12f742a0887eda74a1415610e7157506e085d4780b73119b644ae5ecd22b376905081610eba565b6001600160a01b03841673a5ca62d95d24a4a350983d5b8ac4eb86388873961415610eb457507357ab1ec28d129707052df4df418d58a2d46d5f51905081610eba565b50829050815b9250929050565b610ec96124dc565b6001600160a01b0316610eda611348565b6001600160a01b031614610f23576040805162461bcd60e51b81526020600482018190526024820152600080516020614655833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000610f8f730ac00355f80e289f53bf368c9bdb70f5c114c44b3330866124e0565b6060730ac00355f80e289f53bf368c9bdb70f5c114c44b6001600160a01b031663db5792576040518163ffffffff1660e01b815260040160006040518083038186803b158015610fde57600080fd5b505afa158015610ff2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604090815281101561101b57600080fd5b8101908080516040519392919084600160201b82111561103a57600080fd5b90830190602082018581111561104f57600080fd5b82518660208202830111600160201b8211171561106b57600080fd5b82525081516020918201928201910280838360005b83811015611098578181015183820152602001611080565b5050505090500160405260200180516040519392919084600160201b8211156110c057600080fd5b9083019060208201858111156110d557600080fd5b82518660208202830111600160201b821117156110f157600080fd5b82525081516020918201928201910280838360005b8381101561111e578181015183820152602001611106565b50505050905001604052505050509050730ac00355f80e289f53bf368c9bdb70f5c114c44b6001600160a01b03166342966c68856040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561118857600080fd5b505af115801561119c573d6000803e3d6000fd5b5050505060005b815181101561125c576112548282815181106111bb57fe5b60200260200101518383815181106111cf57fe5b60200260200101516001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561122357600080fd5b505afa158015611237573d6000803e3d6000fd5b505050506040513d602081101561124d57600080fd5b5051612540565b6001016111a3565b50604080516370a0823160e01b8152306004820152905160009173a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48916370a0823191602480820192602092909190829003018186803b1580156112b257600080fd5b505afa1580156112c6573d6000803e3d6000fd5b505050506040513d60208110156112dc57600080fd5b5051905083811015611321576040805162461bcd60e51b8152602060048201526009602482015268216d696e2d7573646360b81b604482015290519081900360640190fd5b61134073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb483383612613565b949350505050565b6000546001600160a01b031690565b61135f6124dc565b6001600160a01b0316611370611348565b6001600160a01b0316146113b9576040805162461bcd60e51b81526020600482018190526024820152600080516020614655833981519152604482015290519081900360640190fd5b61144733826001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561140a57600080fd5b505afa15801561141e573d6000803e3d6000fd5b505050506040513d602081101561143457600080fd5b50516001600160a01b0384169190612613565b50565b600080805b86518110156114885761147e87828151811061146757fe5b60200260200101518361266a90919063ffffffff16565b915060010161144f565b50670de0b6b3a764000081111561149b57fe5b670ddd2935029d80008110156114ad57fe5b6114c26001600160a01b038d1633308e6124e0565b6114cb8c6126c4565b156114e3576114de8c8c89898989612869565b6119b1565b6114ec8c61241c565b15611567578b6001600160a01b0316633ccfd60b6040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561152c57600080fd5b505af1158015611540573d6000803e3d6000fd5b505050506040513d602081101561155657600080fd5b506114de90508a8a89898989612869565b6115708c611dbb565b15611770578b6001600160a01b0316633ccfd60b6040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156115b057600080fd5b505af11580156115c4573d6000803e3d6000fd5b505050506040513d60208110156115da57600080fd5b505060408051637e062a3560e11b815290516000916001600160a01b038f169163fc0c546a91600480820192602092909190829003018186803b15801561162057600080fd5b505afa158015611634573d6000803e3d6000fd5b505050506040513d602081101561164a57600080fd5b5051604080516370a0823160e01b815230600482015290519192506116cd9183916001600160a01b038316916370a0823191602480820192602092909190829003018186803b15801561169c57600080fd5b505afa1580156116b0573d6000803e3d6000fd5b505050506040513d60208110156116c657600080fd5b5051612c5a565b604080516370a0823160e01b8152306004820152905161176a9173a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489182916370a08231916024808301926020929190829003018186803b15801561172457600080fd5b505afa158015611738573d6000803e3d6000fd5b505050506040513d602081101561174e57600080fd5b5051604080516020810190915260008082528c918c9190612869565b506119b1565b6117798c612164565b15611841578b6001600160a01b031663db006a758c6040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b1580156117c457600080fd5b505af11580156117d8573d6000803e3d6000fd5b505050506040513d60208110156117ee57600080fd5b505115611833576040805162461bcd60e51b815260206004820152600e60248201526d2163746f6b656e2d72656465656d60901b604482015290519081900360640190fd5b6114de8a8a89898989612869565b61184a8c6120a4565b1561190a576118786001600160a01b038d16737d2768de32b0b80b7a3454c06bdac94a69ddc7a960006132f8565b6118a06001600160a01b038d16737d2768de32b0b80b7a3454c06bdac94a69ddc7a98d6132f8565b60408051631a4ca37b60e21b81526001600160a01b038c16600482015260001960248201523060448201529051737d2768de32b0b80b7a3454c06bdac94a69ddc7a9916369328dec9160648083019260209291908290030181600087803b15801561152c57600080fd5b6119148c8c612c5a565b604080516370a0823160e01b815230600482015290516119b19173a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489182916370a08231916024808301926020929190829003018186803b15801561196b57600080fd5b505afa15801561197f573d6000803e3d6000fd5b505050506040513d602081101561199557600080fd5b5051604080516020810190915260008082528b918b9190612869565b604080516370a0823160e01b81523060048201529051600091730ac00355f80e289f53bf368c9bdb70f5c114c44b916370a0823191602480820192602092909190829003018186803b158015611a0657600080fd5b505afa158015611a1a573d6000803e3d6000fd5b505050506040513d6020811015611a3057600080fd5b5051905088811015611a75576040805162461bcd60e51b8152602060048201526009602482015268085b5a5b8b5b5a5b9d60ba1b604482015290519081900360640190fd5b611a94730ac00355f80e289f53bf368c9bdb70f5c114c44b3383612613565b8315611b715760005b8851811015611ad157611ac9898281518110611ab557fe5b60200260200101518a83815181106111cf57fe5b600101611a9d565b50604080516370a0823160e01b81523060048201529051611b7191339173a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48916370a08231916024808301926020929190829003018186803b158015611b2957600080fd5b505afa158015611b3d573d6000803e3d6000fd5b505050506040513d6020811015611b5357600080fd5b505173a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489190612613565b9c9b505050505050505050505050565b611b896124dc565b6001600160a01b0316611b9a611348565b6001600160a01b031614611be3576040805162461bcd60e51b81526020600482018190526024820152600080516020614655833981519152604482015290519081900360640190fd5b60005b8151811015611cb557611cad33838381518110611bff57fe5b60200260200101516001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015611c5357600080fd5b505afa158015611c67573d6000803e3d6000fd5b505050506040513d6020811015611c7d57600080fd5b50518451859085908110611c8d57fe5b60200260200101516001600160a01b03166126139092919063ffffffff16565b600101611be6565b5050565b611cc16124dc565b6001600160a01b0316611cd2611348565b6001600160a01b031614611d1b576040805162461bcd60e51b81526020600482018190526024820152600080516020614655833981519152604482015290519081900360640190fd5b6001600160a01b038116611d605760405162461bcd60e51b815260040180806020018281038252602681526020018061460e6026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160a01b038216734b5bfd52124784745c1071dcb244c6688d2533d31480611e0457506001600160a01b038216735a770dbd3ee6baf2802d29a901ef11501c44797a145b80611e2b57506001600160a01b038216738ee57c05741aa9db947a744e713c15d4d19d8822145b80611e5257506001600160a01b038216736ede7f19df5df6ef23bd5b9cedb651580bdf56ca145b80611e7957506001600160a01b03821673c4daf3b5e2a9e93861c3fbdd25f1e943b8d87417145b80611ea057506001600160a01b03821673b4ada607b9d6b2c9ee07a275e9616b84ac560139145b80611ec757506001600160a01b03821673a74d4b67b3368e83797a35382afb776baae4f5c8145b80611eee57506001600160a01b038216735fa5b62c8af877cb37031e0a3b2f34a78e3c56a6145b80611f1557506001600160a01b038216733b96d491f067912d18563d56858ba7d6ec67a6fa145b80611f3c57506001600160a01b0382167384e13785b5a27879921d6f685f041421c7f482da145b80611f6357506001600160a01b0382167327b7b1ad7288079a66d12350c828d3c00a6f07d7145b80611f8a57506001600160a01b038216738cc94ccd0f3841a468184aca3cc478d2148e1757145b80611fb157506001600160a01b038216731c6a9783f812b3af3abbf7de64c3cd7cc7d1af44145b80610a7157506001600160a01b0382167330fcf7c6cdfc46ec237783d94fc78553e79d4e9c1492915050565b600082611fec57506000610a71565b82820282848281611ff957fe5b04146120365760405162461bcd60e51b81526004018080602001828103825260218152602001806146346021913960400191505060405180910390fd5b9392505050565b6000808211612093576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161209c57fe5b049392505050565b60006001600160a01b03821673028171bca77440897b824ca71d1c56cac55b68a314806120ed57506001600160a01b03821673bcca60bb61934080951369a648fb03df4f96263c145b8061211457506001600160a01b038216733ed3b47dd13ec9a98b44e6204a523e766b225811145b8061213b57506001600160a01b03821673101cc05f4a51c0319f570d5e146a8c625198e636145b80610a715750506001600160a01b0316736c5024cd4f8a59110119c56f8933403a539555eb1490565b60006001600160a01b038216735d3a536e4d6dbd6114cc1ead35777bab948e364314806121ad57506001600160a01b0382167339aa39c021dfbae8fac545936693ac917d5e7563145b806121d457506001600160a01b03821673f650c3d88d12db855b8bf7d11be6c55a4e07dcc9145b80610a715750506001600160a01b03167312392f67bdf24fae0af363c24ac620a2f67dad861490565b60006001600160a01b03821673df5e0e81dff6faf3a7e52ba697820c5e32d806a8148061224657506001600160a01b03821673c25a3a3b969415c80451098fa907ec722572917f145b8061226d57506001600160a01b038216733b3ac5386837dc563660fb6a0937dfaa5924333b145b8061229457506001600160a01b038216734807862aa8b2bf68830e4c8dc86d0e9a998e085a145b806122bb57506001600160a01b038216737eb40e450b9655f4b3cc4259bcc731c63ff55ae6145b806122e257506001600160a01b03821673d632f22692fac7611d2aa1c0d552930d43caed3b145b8061230957506001600160a01b0382167343b4fdfd4ff969587185cdb6f0bd875c5fc83f8c145b8061233057506001600160a01b03821673ed279fdd11ca84beef15af5d39bb4d4bee23f0ca145b8061235757506001600160a01b038216736c3f90f043a72fa612cbac8115ee7e52bde6e490145b8061237e57506001600160a01b038216734f3e8f405cf5afc05d68142f3783bdfe13811522145b806123a557506001600160a01b038216733a664ab939fd8482048609f652f9a0b0677337b9145b806123cc57506001600160a01b038216731aef73d49dedc4b1778d0706583995958dc862e6145b806123f357506001600160a01b0382167394e131324b6054c0d789b190b2dac504e4361b53145b80610a715750506001600160a01b0316735282a4ef67d9c33135340fb3289cc1711c13638c1490565b60006001600160a01b0382167319d3364a399d251e894ac732651be8b0e4e85001148061246557506001600160a01b038216735f18c75abdae578b483e5f43f12a39cf75b973a9145b8061248c57506001600160a01b038216737da96a3891add058ada2e826306d812c638d87a7145b806124b357506001600160a01b0382167337d19d1c4e1fa9dc47bd1ea12f742a0887eda74a145b80610a715750506001600160a01b031673a5ca62d95d24a4a350983d5b8ac4eb86388873961490565b3390565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b17905261253a908590613407565b50505050565b61254982611dbb565b15611cb557611cb5826001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561258a57600080fd5b505afa15801561259e573d6000803e3d6000fd5b505050506040513d60208110156125b457600080fd5b505160408051632e1a7d4d60e01b81526004810185905290516001600160a01b03861691632e1a7d4d9160248083019260209291908290030181600087803b1580156125ff57600080fd5b505af11580156116b0573d6000803e3d6000fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052612665908490613407565b505050565b600082820183811015612036576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60006001600160a01b038216736b175474e89094c44da98b954eedeac495271d0f148061270d57506001600160a01b03821673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48145b8061273457506001600160a01b03821673dac17f958d2ee523a2206206994597c13d831ec7145b8061275657506001600160a01b0382166e085d4780b73119b644ae5ecd22b376145b8061277d57506001600160a01b0382167357ab1ec28d129707052df4df418d58a2d46d5f51145b806127a457506001600160a01b038216734fabb145d64652a948d72533023f6e7a623c7c53145b806127cb57506001600160a01b038216731456688345527be1f37e9e627da0837d6f08c925145b806127f257506001600160a01b03821673853d955acef822db058eb8505911ed77f175b99e145b8061281957506001600160a01b03821673bc6da0fe9ad5f3b0d58160288917aa56653660e9145b8061284057506001600160a01b038216735f98805a4e8be255a32880fdec7f6728c6568ba0145b80610a715750506001600160a01b031673674c6ad92fd080e4004b2312b45f796a192d27a01490565b60006001600160a01b038716736b175474e89094c44da98b954eedeac495271d0f148015906128b557506001600160a01b03871673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4814155b80156128de57506001600160a01b03871673dac17f958d2ee523a2206206994597c13d831ec714155b15612a06576128f86001600160a01b0388168460006132f8565b61290c6001600160a01b03881684886132f8565b6000836001600160a01b0316836040518082805190602001908083835b602083106129485780518252601f199092019160209182019101612929565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146129aa576040519150601f19603f3d011682016040523d82523d6000602084013e6129af565b606091505b50509050806129ed576040805162461bcd60e51b8152602060048201526005602482015264021737761760dc1b604482015290519081900360640190fd5b73a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489750505b6001600160a01b03871673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb481415612a3357506001612a5c565b6001600160a01b03871673dac17f958d2ee523a2206206994597c13d831ec71415612a5c575060025b600080730ac00355f80e289f53bf368c9bdb70f5c114c44b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015612aac57600080fd5b505afa158015612ac0573d6000803e3d6000fd5b505050506040513d6020811015612ad657600080fd5b5051604080516370a0823160e01b815230600482015290519192506000916001600160a01b038c16916370a08231916024808301926020929190829003018186803b158015612b2457600080fd5b505afa158015612b38573d6000803e3d6000fd5b505050506040513d6020811015612b4e57600080fd5b505190506000805b8951811015612bda57612b91670de0b6b3a76400006104d58b8481518110612b7a57fe5b602002602001015186611fdd90919063ffffffff16565b9150612bb28c8b8381518110612ba357fe5b602002602001015184896134b8565b612bd0848b8381518110612bc257fe5b60200260200101518761425b565b9450600101612b56565b50730ac00355f80e289f53bf368c9bdb70f5c114c44b6001600160a01b031663a0712d68856040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015612c3557600080fd5b505af1158015612c49573d6000803e3d6000fd5b505050505050505050505050505050565b6001600160a01b03821673df5e0e81dff6faf3a7e52ba697820c5e32d806a81480612ca157506001600160a01b03821673c25a3a3b969415c80451098fa907ec722572917f145b80612cc857506001600160a01b038216733b3ac5386837dc563660fb6a0937dfaa5924333b145b15612e005773bbc81d23ea2c3ec7e56d39296f0cbb648873a5d36001600160a01b03831673c25a3a3b969415c80451098fa907ec722572917f1415612d22575073fcba3e75865d2d561be8d220616520c171f12851612d5e565b6001600160a01b038316733b3ac5386837dc563660fb6a0937dfaa5924333b1415612d5e575073b6c057591e073249f2d9d88ba59a46cfc9b59edb5b612d736001600160a01b0384168260006132f8565b612d876001600160a01b03841682846132f8565b6040805163517a55a360e01b815260048101849052600160248201526000604482018190526064820181905291516001600160a01b0384169263517a55a3926084808201939182900301818387803b158015612de257600080fd5b505af1158015612df6573d6000803e3d6000fd5b5050505050611cb5565b6001600160a01b038216737eb40e450b9655f4b3cc4259bcc731c63ff55ae61480612e4757506001600160a01b038216734f3e8f405cf5afc05d68142f3783bdfe13811522145b80612e6e57506001600160a01b038216733a664ab939fd8482048609f652f9a0b0677337b9145b80612e9557506001600160a01b038216731aef73d49dedc4b1778d0706583995958dc862e6145b80612ebc57506001600160a01b0382167394e131324b6054c0d789b190b2dac504e4361b53145b1561304f5773094d12e5b541784701fd8d65f11fc0598fbc63326001600160a01b038316737eb40e450b9655f4b3cc4259bcc731c63ff55ae61415612f165750733c8caee4e09296800f8d29a68fa3837e2dae4940612fd2565b6001600160a01b038316733a664ab939fd8482048609f652f9a0b0677337b91415612f5657507361e10659fe3aa93d036d099405224e4ac24996d0612fd2565b6001600160a01b038316731aef73d49dedc4b1778d0706583995958dc862e61415612f96575073803a2b40c5a9bb2b86dd630b274fa2a9202874c2612fd2565b6001600160a01b0383167394e131324b6054c0d789b190b2dac504e4361b531415612fd2575073b0a0716841f2fc03fba72a891b8bb13584f52f2d5b612fe76001600160a01b0384168260006132f8565b612ffb6001600160a01b03841682846132f8565b60408051630d2680e960e11b8152600481018490526002602482015260006044820181905291516001600160a01b03841692631a4d01d2926064808201939182900301818387803b158015612de257600080fd5b6001600160a01b038216735282a4ef67d9c33135340fb3289cc1711c13638c141561314b5761309d6001600160a01b038316732dded6da1bf5dbdf597c45fcfaa3194e53ecfeaf60006132f8565b6130c56001600160a01b038316732dded6da1bf5dbdf597c45fcfaa3194e53ecfeaf836132f8565b6040805163517a55a360e01b81526004810183905260016024820181905260006044830181905260648301919091529151732dded6da1bf5dbdf597c45fcfaa3194e53ecfeaf9263517a55a3926084808201939182900301818387803b15801561312e57600080fd5b505af1158015613142573d6000803e3d6000fd5b50505050611cb5565b6001600160a01b038216736c3f90f043a72fa612cbac8115ee7e52bde6e49014156132025773bebc44782c7db0a1a60cb6fe97d0b483032ff1c761319a6001600160a01b0384168260006132f8565b6131ae6001600160a01b03841682846132f8565b60408051630d2680e960e11b8152600481018490526001602482015260006044820181905291516001600160a01b03841692631a4d01d2926064808201939182900301818387803b158015612de257600080fd5b61322b6001600160a01b03831673a79828df1850e8a3a3064576f380d90aecdd335960006132f8565b6132536001600160a01b03831673a79828df1850e8a3a3064576f380d90aecdd3359836132f8565b60408051631e700cbb60e01b81526001600160a01b03841660048201526024810183905260026044820152600060648201819052306084830152915173a79828df1850e8a3a3064576f380d90aecdd335992631e700cbb9260a480820193602093909283900390910190829087803b1580156132ce57600080fd5b505af11580156132e2573d6000803e3d6000fd5b505050506040513d602081101561253a57600080fd5b80158061337e575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b15801561335057600080fd5b505afa158015613364573d6000803e3d6000fd5b505050506040513d602081101561337a57600080fd5b5051155b6133b95760405162461bcd60e51b815260040180806020018281038252603681526020018061469f6036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b1790526126659084905b606061345c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166144019092919063ffffffff16565b8051909150156126655780806020019051602081101561347b57600080fd5b50516126655760405162461bcd60e51b815260040180806020018281038252602a815260200180614675602a913960400191505060405180910390fd5b60006134c26145d1565b60405180608001604052806000815260200160008152602001600081526020016000815250905073a5ca62d95d24a4a350983d5b8ac4eb86388873966001600160a01b0316856001600160a01b031614156136d4576135406001600160a01b03871673a5407eae9ba41422680e2e00537571bcc53efbfd60006132f8565b6135686001600160a01b03871673a5407eae9ba41422680e2e00537571bcc53efbfd866132f8565b60408051630f7c084960e21b8152600f85900b60048201526003602482015260448101869052600060648201819052915173a5407eae9ba41422680e2e00537571bcc53efbfd92633df02124926084808201939182900301818387803b1580156135d157600080fd5b505af11580156135e5573d6000803e3d6000fd5b5050604080516370a0823160e01b815230600482015290517357ab1ec28d129707052df4df418d58a2d46d5f5193506370a0823192506024808301926020929190829003018186803b15801561363a57600080fd5b505afa15801561364e573d6000803e3d6000fd5b505050506040513d602081101561366457600080fd5b5051915061369c7357ab1ec28d129707052df4df418d58a2d46d5f5173a5ca62d95d24a4a350983d5b8ac4eb863888739660006132f8565b6136cf7357ab1ec28d129707052df4df418d58a2d46d5f5173a5ca62d95d24a4a350983d5b8ac4eb8638887396846132f8565b6141ec565b6001600160a01b038516734b5bfd52124784745c1071dcb244c6688d2533d3148061371b57506001600160a01b038516735a770dbd3ee6baf2802d29a901ef11501c44797a145b8061374257506001600160a01b038516738ee57c05741aa9db947a744e713c15d4d19d8822145b8061376957506001600160a01b038516733b96d491f067912d18563d56858ba7d6ec67a6fa145b8061379057506001600160a01b03851673c4daf3b5e2a9e93861c3fbdd25f1e943b8d87417145b806137b757506001600160a01b0385167330fcf7c6cdfc46ec237783d94fc78553e79d4e9c145b806137de57506001600160a01b038516738cc94ccd0f3841a468184aca3cc478d2148e1757145b8061380557506001600160a01b038516731c6a9783f812b3af3abbf7de64c3cd7cc7d1af44145b15613bcf576000856001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561384557600080fd5b505afa158015613859573d6000803e3d6000fd5b505050506040513d602081101561386f57600080fd5b5051905073bbc81d23ea2c3ec7e56d39296f0cbb648873a5d36001600160a01b038716735a770dbd3ee6baf2802d29a901ef11501c44797a14156138c8575073fcba3e75865d2d561be8d220616520c171f12851613a67565b6001600160a01b038716738ee57c05741aa9db947a744e713c15d4d19d88221415613908575073b6c057591e073249f2d9d88ba59a46cfc9b59edb613a67565b6001600160a01b038716733b96d491f067912d18563d56858ba7d6ec67a6fa141561394f5773094d12e5b541784701fd8d65f11fc0598fbc63329050600185019450613a67565b6001600160a01b03871673c4daf3b5e2a9e93861c3fbdd25f1e943b8d87417141561399657733c8caee4e09296800f8d29a68fa3837e2dae49409050600185019450613a67565b6001600160a01b0387167330fcf7c6cdfc46ec237783d94fc78553e79d4e9c14156139dd577361e10659fe3aa93d036d099405224e4ac24996d09050600185019450613a67565b6001600160a01b038716738cc94ccd0f3841a468184aca3cc478d2148e17571415613a245773803a2b40c5a9bb2b86dd630b274fa2a9202874c29050600185019450613a67565b6001600160a01b038716731c6a9783f812b3af3abbf7de64c3cd7cc7d1af441415613a675773b0a0716841f2fc03fba72a891b8bb13584f52f2d90506001850194505b85838660048110613a7457fe5b6020020152613a8e6001600160a01b0389168260006132f8565b613aa26001600160a01b03891682886132f8565b60405162a6cbcd60e21b81526001600160a01b0382169063029b2f3490859060009060040180836080808383875b83811015613ae8578181015183820152602001613ad0565b5050505090500182815260200192505050600060405180830381600087803b158015613b1357600080fd5b505af1158015613b27573d6000803e3d6000fd5b5050604080516370a0823160e01b815230600482015290516001600160a01b03861693506370a0823192506024808301926020929190829003018186803b158015613b7157600080fd5b505afa158015613b85573d6000803e3d6000fd5b505050506040513d6020811015613b9b57600080fd5b50519350613bb46001600160a01b0383168860006132f8565b613bc86001600160a01b03831688866132f8565b50506141ec565b6001600160a01b0385167384e13785b5a27879921d6f685f041421c7f482da1480613c1657506001600160a01b0385167327b7b1ad7288079a66d12350c828d3c00a6f07d7145b15613f28576000856001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b158015613c5657600080fd5b505afa158015613c6a573d6000803e3d6000fd5b505050506040513d6020811015613c8057600080fd5b50519050613c8c6145ef565b604051806060016040528060008152602001600081526020016000815250905085818660038110613cb957fe5b602002015273bebc44782c7db0a1a60cb6fe97d0b483032ff1c76001600160a01b0388167327b7b1ad7288079a66d12350c828d3c00a6f07d71415613d0f5750732dded6da1bf5dbdf597c45fcfaa3194e53ecfeaf5b613d246001600160a01b038a168260006132f8565b613d386001600160a01b038a1682896132f8565b6001600160a01b0388167384e13785b5a27879921d6f685f041421c7f482da1415613dec57604051634515cef360e01b81526001600160a01b03821690634515cef390849060009060040180836060808383875b83811015613da4578181015183820152602001613d8c565b5050505090500182815260200192505050600060405180830381600087803b158015613dcf57600080fd5b505af1158015613de3573d6000803e3d6000fd5b50505050613e83565b6040516315b74c9d60e11b81526001600160a01b03821690632b6e993a90849060009060019060040180846060808383885b83811015613e36578181015183820152602001613e1e565b5050505090500183815260200182151581526020019350505050600060405180830381600087803b158015613e6a57600080fd5b505af1158015613e7e573d6000803e3d6000fd5b505050505b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b158015613ec957600080fd5b505afa158015613edd573d6000803e3d6000fd5b505050506040513d6020811015613ef357600080fd5b50519450613f0c6001600160a01b0384168960006132f8565b613f206001600160a01b03841689876132f8565b5050506141ec565b6001600160a01b038516736ede7f19df5df6ef23bd5b9cedb651580bdf56ca1480613f6f57506001600160a01b03851673b4ada607b9d6b2c9ee07a275e9616b84ac560139145b80613f9657506001600160a01b03851673a74d4b67b3368e83797a35382afb776baae4f5c8145b80613fbd57506001600160a01b038516735fa5b62c8af877cb37031e0a3b2f34a78e3c56a6145b156141ec576000856001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b158015613ffd57600080fd5b505afa158015614011573d6000803e3d6000fd5b505050506040513d602081101561402757600080fd5b505190508482600186016004811061403b57fe5b60200201526140696001600160a01b03881673a79828df1850e8a3a3064576f380d90aecdd335960006132f8565b6140916001600160a01b03881673a79828df1850e8a3a3064576f380d90aecdd3359876132f8565b60405163384e03db60e01b81526001600160a01b0382166004820190815273a79828df1850e8a3a3064576f380d90aecdd33599163384e03db9184918691600091602401836080808383875b838110156140f55781810151838201526020016140dd565b505050509050018281526020019350505050602060405180830381600087803b15801561412157600080fd5b505af1158015614135573d6000803e3d6000fd5b505050506040513d602081101561414b57600080fd5b5050604080516370a0823160e01b815230600482015290516001600160a01b038316916370a08231916024808301926020929190829003018186803b15801561419357600080fd5b505afa1580156141a7573d6000803e3d6000fd5b505050506040513d60208110156141bd57600080fd5b505192506141d66001600160a01b0382168760006132f8565b6141ea6001600160a01b03821687856132f8565b505b846001600160a01b031663d0e30db06040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561422757600080fd5b505af115801561423b573d6000803e3d6000fd5b505050506040513d602081101561425157600080fd5b5050505050505050565b600080836001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156142ab57600080fd5b505afa1580156142bf573d6000803e3d6000fd5b505050506040513d60208110156142d557600080fd5b5051604080516370a0823160e01b8152730ac00355f80e289f53bf368c9bdb70f5c114c44b600482015290519192506000916001600160a01b038716916370a08231916024808301926020929190829003018186803b15801561433757600080fd5b505afa15801561434b573d6000803e3d6000fd5b505050506040513d602081101561436157600080fd5b5051905061438e6001600160a01b038616730ac00355f80e289f53bf368c9bdb70f5c114c44b60006132f8565b6143b66001600160a01b038616730ac00355f80e289f53bf368c9bdb70f5c114c44b846132f8565b836143d2576143c9816104d58885611fdd565b92505050612036565b60006143e2826104d58986611fdd565b9050848110156143f6579250612036915050565b509295945050505050565b606061134084846000858561441585614527565b614466576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106144a55780518252601f199092019160209182019101614486565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614507576040519150601f19603f3d011682016040523d82523d6000602084013e61450c565b606091505b509150915061451c82828661452d565b979650505050505050565b3b151590565b6060831561453c575081612036565b82511561454c5782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561459657818101518382015260200161457e565b50505050905090810190601f1680156145c35780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b60405180608001604052806004906020820280368337509192915050565b6040518060600160405280600390602082028036833750919291505056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a264697066735822122033743fb3c2c81f206225ae17c7a957755ba167cd8c6bbf0f2897e84d1c4b0dcd64736f6c63430007030033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100935760003560e01c80638da5cb5b116100665780638da5cb5b146101525780639e8c708e14610176578063a063c0421461019c578063a7a580d514610383578063f2fde38b1461042457610093565b806331bceb48146100985780636331f17f146100d6578063715018a6146101255780637a991e121461012f575b600080fd5b6100c4600480360360408110156100ae57600080fd5b506001600160a01b03813516906020013561044a565b60408051918252519081900360200190f35b610102600480360360408110156100ec57600080fd5b506001600160a01b038135169060200135610a77565b604080516001600160a01b03909316835260208301919091528051918290030190f35b61012d610ec1565b005b6100c46004803603604081101561014557600080fd5b5080359060200135610f6d565b61015a611348565b604080516001600160a01b039092168252519081900360200190f35b61012d6004803603602081101561018c57600080fd5b50356001600160a01b0316611357565b6100c460048036036101408110156101b357600080fd5b6001600160a01b03823581169260208101359260408201359092169160608201359160808101359181019060c0810160a0820135600160201b8111156101f857600080fd5b82018360208201111561020a57600080fd5b803590602001918460208302840111600160201b8311171561022b57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561027a57600080fd5b82018360208201111561028c57600080fd5b803590602001918460208302840111600160201b831117156102ad57600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092956001600160a01b03853516959094909350604081019250602001359050600160201b81111561030d57600080fd5b82018360208201111561031f57600080fd5b803590602001918460018302840111600160201b8311171561034057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505050351515905061144a565b61012d6004803603602081101561039957600080fd5b810190602081018135600160201b8111156103b357600080fd5b8201836020820111156103c557600080fd5b803590602001918460208302840111600160201b831117156103e657600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611b81945050505050565b61012d6004803603602081101561043a57600080fd5b50356001600160a01b0316611cb9565b600061045583611dbb565b15610545576104db670de0b6b3a76400006104d5856001600160a01b03166399530b066040518163ffffffff1660e01b815260040160206040518083038186803b1580156104a257600080fd5b505afa1580156104b6573d6000803e3d6000fd5b505050506040513d60208110156104cc57600080fd5b50518590611fdd565b9061203d565b9150826001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561051657600080fd5b505afa15801561052a573d6000803e3d6000fd5b505050506040513d602081101561054057600080fd5b505192505b6001600160a01b03831673df5e0e81dff6faf3a7e52ba697820c5e32d806a8148061058c57506001600160a01b03831673c25a3a3b969415c80451098fa907ec722572917f145b806105b357506001600160a01b038316736c3f90f043a72fa612cbac8115ee7e52bde6e490145b806105da57506001600160a01b038316733b3ac5386837dc563660fb6a0937dfaa5924333b145b156107325773bbc81d23ea2c3ec7e56d39296f0cbb648873a5d36001600160a01b03841673c25a3a3b969415c80451098fa907ec722572917f1415610634575073fcba3e75865d2d561be8d220616520c171f128516106b0565b6001600160a01b038416736c3f90f043a72fa612cbac8115ee7e52bde6e4901415610674575073bebc44782c7db0a1a60cb6fe97d0b483032ff1c76106b0565b6001600160a01b038416733b3ac5386837dc563660fb6a0937dfaa5924333b14156106b0575073b6c057591e073249f2d9d88ba59a46cfc9b59edb5b806001600160a01b031663cc2b27d78460016040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156106fd57600080fd5b505afa158015610711573d6000803e3d6000fd5b505050506040513d602081101561072757600080fd5b50519150610a719050565b6001600160a01b038316734f3e8f405cf5afc05d68142f3783bdfe13811522148061077957506001600160a01b038316737eb40e450b9655f4b3cc4259bcc731c63ff55ae6145b806107a057506001600160a01b038316733a664ab939fd8482048609f652f9a0b0677337b9145b806107c757506001600160a01b038316731aef73d49dedc4b1778d0706583995958dc862e6145b806107ee57506001600160a01b0383167394e131324b6054c0d789b190b2dac504e4361b53145b156109515773094d12e5b541784701fd8d65f11fc0598fbc63326001600160a01b038416737eb40e450b9655f4b3cc4259bcc731c63ff55ae614156108485750733c8caee4e09296800f8d29a68fa3837e2dae4940610904565b6001600160a01b038416733a664ab939fd8482048609f652f9a0b0677337b9141561088857507361e10659fe3aa93d036d099405224e4ac24996d0610904565b6001600160a01b038416731aef73d49dedc4b1778d0706583995958dc862e614156108c8575073803a2b40c5a9bb2b86dd630b274fa2a9202874c2610904565b6001600160a01b0384167394e131324b6054c0d789b190b2dac504e4361b531415610904575073b0a0716841f2fc03fba72a891b8bb13584f52f2d5b806001600160a01b031663cc2b27d78460026040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156106fd57600080fd5b6001600160a01b038316735282a4ef67d9c33135340fb3289cc1711c13638c1415610a09576040805163314ca9dd60e21b81526004810184905260016024820181905260448201529051732dded6da1bf5dbdf597c45fcfaa3194e53ecfeaf9163c532a774916064808301926020929190829003018186803b1580156109d657600080fd5b505afa1580156109ea573d6000803e3d6000fd5b505050506040513d6020811015610a0057600080fd5b50519050610a71565b604080516341b028f360e01b81526001600160a01b03851660048201526024810184905260026044820152905173a79828df1850e8a3a3064576f380d90aecdd3359916341b028f3916064808301926020929190829003018186803b1580156109d657600080fd5b92915050565b600080610a83846120a4565b15610af757836001600160a01b031663b16a19de6040518163ffffffff1660e01b815260040160206040518083038186803b158015610ac157600080fd5b505afa158015610ad5573d6000803e3d6000fd5b505050506040513d6020811015610aeb57600080fd5b50519150829050610eba565b610b0084612164565b15610c9a576000846001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b158015610b4057600080fd5b505afa158015610b54573d6000803e3d6000fd5b505050506040513d6020811015610b6a57600080fd5b505160408051636f307dc360e01b815290519192506000916001600160a01b03881691636f307dc3916004808301926020929190829003018186803b158015610bb257600080fd5b505afa158015610bc6573d6000803e3d6000fd5b505050506040513d6020811015610bdc57600080fd5b50516040805163313ce56760e01b815290519192506000916001600160a01b0384169163313ce567916004808301926020929190829003018186803b158015610c2457600080fd5b505afa158015610c38573d6000803e3d6000fd5b505050506040513d6020811015610c4e57600080fd5b505160ff169050600a80820190600090610c779083900a6104d587670de0b6b3a7640000611fdd565b905083610c8c6305f5e1006104d58b85611fdd565b965096505050505050610eba565b610ca3846121fd565b80610cb25750610cb284611dbb565b15610cdf5773a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48610cd6858561044a565b91509150610eba565b610ce88461241c565b15610eb457610d68670de0b6b3a76400006104d5866001600160a01b03166399530b066040518163ffffffff1660e01b815260040160206040518083038186803b158015610d3557600080fd5b505afa158015610d49573d6000803e3d6000fd5b505050506040513d6020811015610d5f57600080fd5b50518690611fdd565b92506001600160a01b0384167319d3364a399d251e894ac732651be8b0e4e850011415610dad5750736b175474e89094c44da98b954eedeac495271d0f905081610eba565b6001600160a01b038416735f18c75abdae578b483e5f43f12a39cf75b973a91415610df0575073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48905081610eba565b6001600160a01b038416737da96a3891add058ada2e826306d812c638d87a71415610e33575073dac17f958d2ee523a2206206994597c13d831ec7905081610eba565b6001600160a01b0384167337d19d1c4e1fa9dc47bd1ea12f742a0887eda74a1415610e7157506e085d4780b73119b644ae5ecd22b376905081610eba565b6001600160a01b03841673a5ca62d95d24a4a350983d5b8ac4eb86388873961415610eb457507357ab1ec28d129707052df4df418d58a2d46d5f51905081610eba565b50829050815b9250929050565b610ec96124dc565b6001600160a01b0316610eda611348565b6001600160a01b031614610f23576040805162461bcd60e51b81526020600482018190526024820152600080516020614655833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000610f8f730ac00355f80e289f53bf368c9bdb70f5c114c44b3330866124e0565b6060730ac00355f80e289f53bf368c9bdb70f5c114c44b6001600160a01b031663db5792576040518163ffffffff1660e01b815260040160006040518083038186803b158015610fde57600080fd5b505afa158015610ff2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604090815281101561101b57600080fd5b8101908080516040519392919084600160201b82111561103a57600080fd5b90830190602082018581111561104f57600080fd5b82518660208202830111600160201b8211171561106b57600080fd5b82525081516020918201928201910280838360005b83811015611098578181015183820152602001611080565b5050505090500160405260200180516040519392919084600160201b8211156110c057600080fd5b9083019060208201858111156110d557600080fd5b82518660208202830111600160201b821117156110f157600080fd5b82525081516020918201928201910280838360005b8381101561111e578181015183820152602001611106565b50505050905001604052505050509050730ac00355f80e289f53bf368c9bdb70f5c114c44b6001600160a01b03166342966c68856040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561118857600080fd5b505af115801561119c573d6000803e3d6000fd5b5050505060005b815181101561125c576112548282815181106111bb57fe5b60200260200101518383815181106111cf57fe5b60200260200101516001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561122357600080fd5b505afa158015611237573d6000803e3d6000fd5b505050506040513d602081101561124d57600080fd5b5051612540565b6001016111a3565b50604080516370a0823160e01b8152306004820152905160009173a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48916370a0823191602480820192602092909190829003018186803b1580156112b257600080fd5b505afa1580156112c6573d6000803e3d6000fd5b505050506040513d60208110156112dc57600080fd5b5051905083811015611321576040805162461bcd60e51b8152602060048201526009602482015268216d696e2d7573646360b81b604482015290519081900360640190fd5b61134073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb483383612613565b949350505050565b6000546001600160a01b031690565b61135f6124dc565b6001600160a01b0316611370611348565b6001600160a01b0316146113b9576040805162461bcd60e51b81526020600482018190526024820152600080516020614655833981519152604482015290519081900360640190fd5b61144733826001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561140a57600080fd5b505afa15801561141e573d6000803e3d6000fd5b505050506040513d602081101561143457600080fd5b50516001600160a01b0384169190612613565b50565b600080805b86518110156114885761147e87828151811061146757fe5b60200260200101518361266a90919063ffffffff16565b915060010161144f565b50670de0b6b3a764000081111561149b57fe5b670ddd2935029d80008110156114ad57fe5b6114c26001600160a01b038d1633308e6124e0565b6114cb8c6126c4565b156114e3576114de8c8c89898989612869565b6119b1565b6114ec8c61241c565b15611567578b6001600160a01b0316633ccfd60b6040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561152c57600080fd5b505af1158015611540573d6000803e3d6000fd5b505050506040513d602081101561155657600080fd5b506114de90508a8a89898989612869565b6115708c611dbb565b15611770578b6001600160a01b0316633ccfd60b6040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156115b057600080fd5b505af11580156115c4573d6000803e3d6000fd5b505050506040513d60208110156115da57600080fd5b505060408051637e062a3560e11b815290516000916001600160a01b038f169163fc0c546a91600480820192602092909190829003018186803b15801561162057600080fd5b505afa158015611634573d6000803e3d6000fd5b505050506040513d602081101561164a57600080fd5b5051604080516370a0823160e01b815230600482015290519192506116cd9183916001600160a01b038316916370a0823191602480820192602092909190829003018186803b15801561169c57600080fd5b505afa1580156116b0573d6000803e3d6000fd5b505050506040513d60208110156116c657600080fd5b5051612c5a565b604080516370a0823160e01b8152306004820152905161176a9173a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489182916370a08231916024808301926020929190829003018186803b15801561172457600080fd5b505afa158015611738573d6000803e3d6000fd5b505050506040513d602081101561174e57600080fd5b5051604080516020810190915260008082528c918c9190612869565b506119b1565b6117798c612164565b15611841578b6001600160a01b031663db006a758c6040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b1580156117c457600080fd5b505af11580156117d8573d6000803e3d6000fd5b505050506040513d60208110156117ee57600080fd5b505115611833576040805162461bcd60e51b815260206004820152600e60248201526d2163746f6b656e2d72656465656d60901b604482015290519081900360640190fd5b6114de8a8a89898989612869565b61184a8c6120a4565b1561190a576118786001600160a01b038d16737d2768de32b0b80b7a3454c06bdac94a69ddc7a960006132f8565b6118a06001600160a01b038d16737d2768de32b0b80b7a3454c06bdac94a69ddc7a98d6132f8565b60408051631a4ca37b60e21b81526001600160a01b038c16600482015260001960248201523060448201529051737d2768de32b0b80b7a3454c06bdac94a69ddc7a9916369328dec9160648083019260209291908290030181600087803b15801561152c57600080fd5b6119148c8c612c5a565b604080516370a0823160e01b815230600482015290516119b19173a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489182916370a08231916024808301926020929190829003018186803b15801561196b57600080fd5b505afa15801561197f573d6000803e3d6000fd5b505050506040513d602081101561199557600080fd5b5051604080516020810190915260008082528b918b9190612869565b604080516370a0823160e01b81523060048201529051600091730ac00355f80e289f53bf368c9bdb70f5c114c44b916370a0823191602480820192602092909190829003018186803b158015611a0657600080fd5b505afa158015611a1a573d6000803e3d6000fd5b505050506040513d6020811015611a3057600080fd5b5051905088811015611a75576040805162461bcd60e51b8152602060048201526009602482015268085b5a5b8b5b5a5b9d60ba1b604482015290519081900360640190fd5b611a94730ac00355f80e289f53bf368c9bdb70f5c114c44b3383612613565b8315611b715760005b8851811015611ad157611ac9898281518110611ab557fe5b60200260200101518a83815181106111cf57fe5b600101611a9d565b50604080516370a0823160e01b81523060048201529051611b7191339173a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48916370a08231916024808301926020929190829003018186803b158015611b2957600080fd5b505afa158015611b3d573d6000803e3d6000fd5b505050506040513d6020811015611b5357600080fd5b505173a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489190612613565b9c9b505050505050505050505050565b611b896124dc565b6001600160a01b0316611b9a611348565b6001600160a01b031614611be3576040805162461bcd60e51b81526020600482018190526024820152600080516020614655833981519152604482015290519081900360640190fd5b60005b8151811015611cb557611cad33838381518110611bff57fe5b60200260200101516001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015611c5357600080fd5b505afa158015611c67573d6000803e3d6000fd5b505050506040513d6020811015611c7d57600080fd5b50518451859085908110611c8d57fe5b60200260200101516001600160a01b03166126139092919063ffffffff16565b600101611be6565b5050565b611cc16124dc565b6001600160a01b0316611cd2611348565b6001600160a01b031614611d1b576040805162461bcd60e51b81526020600482018190526024820152600080516020614655833981519152604482015290519081900360640190fd5b6001600160a01b038116611d605760405162461bcd60e51b815260040180806020018281038252602681526020018061460e6026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160a01b038216734b5bfd52124784745c1071dcb244c6688d2533d31480611e0457506001600160a01b038216735a770dbd3ee6baf2802d29a901ef11501c44797a145b80611e2b57506001600160a01b038216738ee57c05741aa9db947a744e713c15d4d19d8822145b80611e5257506001600160a01b038216736ede7f19df5df6ef23bd5b9cedb651580bdf56ca145b80611e7957506001600160a01b03821673c4daf3b5e2a9e93861c3fbdd25f1e943b8d87417145b80611ea057506001600160a01b03821673b4ada607b9d6b2c9ee07a275e9616b84ac560139145b80611ec757506001600160a01b03821673a74d4b67b3368e83797a35382afb776baae4f5c8145b80611eee57506001600160a01b038216735fa5b62c8af877cb37031e0a3b2f34a78e3c56a6145b80611f1557506001600160a01b038216733b96d491f067912d18563d56858ba7d6ec67a6fa145b80611f3c57506001600160a01b0382167384e13785b5a27879921d6f685f041421c7f482da145b80611f6357506001600160a01b0382167327b7b1ad7288079a66d12350c828d3c00a6f07d7145b80611f8a57506001600160a01b038216738cc94ccd0f3841a468184aca3cc478d2148e1757145b80611fb157506001600160a01b038216731c6a9783f812b3af3abbf7de64c3cd7cc7d1af44145b80610a7157506001600160a01b0382167330fcf7c6cdfc46ec237783d94fc78553e79d4e9c1492915050565b600082611fec57506000610a71565b82820282848281611ff957fe5b04146120365760405162461bcd60e51b81526004018080602001828103825260218152602001806146346021913960400191505060405180910390fd5b9392505050565b6000808211612093576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161209c57fe5b049392505050565b60006001600160a01b03821673028171bca77440897b824ca71d1c56cac55b68a314806120ed57506001600160a01b03821673bcca60bb61934080951369a648fb03df4f96263c145b8061211457506001600160a01b038216733ed3b47dd13ec9a98b44e6204a523e766b225811145b8061213b57506001600160a01b03821673101cc05f4a51c0319f570d5e146a8c625198e636145b80610a715750506001600160a01b0316736c5024cd4f8a59110119c56f8933403a539555eb1490565b60006001600160a01b038216735d3a536e4d6dbd6114cc1ead35777bab948e364314806121ad57506001600160a01b0382167339aa39c021dfbae8fac545936693ac917d5e7563145b806121d457506001600160a01b03821673f650c3d88d12db855b8bf7d11be6c55a4e07dcc9145b80610a715750506001600160a01b03167312392f67bdf24fae0af363c24ac620a2f67dad861490565b60006001600160a01b03821673df5e0e81dff6faf3a7e52ba697820c5e32d806a8148061224657506001600160a01b03821673c25a3a3b969415c80451098fa907ec722572917f145b8061226d57506001600160a01b038216733b3ac5386837dc563660fb6a0937dfaa5924333b145b8061229457506001600160a01b038216734807862aa8b2bf68830e4c8dc86d0e9a998e085a145b806122bb57506001600160a01b038216737eb40e450b9655f4b3cc4259bcc731c63ff55ae6145b806122e257506001600160a01b03821673d632f22692fac7611d2aa1c0d552930d43caed3b145b8061230957506001600160a01b0382167343b4fdfd4ff969587185cdb6f0bd875c5fc83f8c145b8061233057506001600160a01b03821673ed279fdd11ca84beef15af5d39bb4d4bee23f0ca145b8061235757506001600160a01b038216736c3f90f043a72fa612cbac8115ee7e52bde6e490145b8061237e57506001600160a01b038216734f3e8f405cf5afc05d68142f3783bdfe13811522145b806123a557506001600160a01b038216733a664ab939fd8482048609f652f9a0b0677337b9145b806123cc57506001600160a01b038216731aef73d49dedc4b1778d0706583995958dc862e6145b806123f357506001600160a01b0382167394e131324b6054c0d789b190b2dac504e4361b53145b80610a715750506001600160a01b0316735282a4ef67d9c33135340fb3289cc1711c13638c1490565b60006001600160a01b0382167319d3364a399d251e894ac732651be8b0e4e85001148061246557506001600160a01b038216735f18c75abdae578b483e5f43f12a39cf75b973a9145b8061248c57506001600160a01b038216737da96a3891add058ada2e826306d812c638d87a7145b806124b357506001600160a01b0382167337d19d1c4e1fa9dc47bd1ea12f742a0887eda74a145b80610a715750506001600160a01b031673a5ca62d95d24a4a350983d5b8ac4eb86388873961490565b3390565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b17905261253a908590613407565b50505050565b61254982611dbb565b15611cb557611cb5826001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561258a57600080fd5b505afa15801561259e573d6000803e3d6000fd5b505050506040513d60208110156125b457600080fd5b505160408051632e1a7d4d60e01b81526004810185905290516001600160a01b03861691632e1a7d4d9160248083019260209291908290030181600087803b1580156125ff57600080fd5b505af11580156116b0573d6000803e3d6000fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052612665908490613407565b505050565b600082820183811015612036576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60006001600160a01b038216736b175474e89094c44da98b954eedeac495271d0f148061270d57506001600160a01b03821673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48145b8061273457506001600160a01b03821673dac17f958d2ee523a2206206994597c13d831ec7145b8061275657506001600160a01b0382166e085d4780b73119b644ae5ecd22b376145b8061277d57506001600160a01b0382167357ab1ec28d129707052df4df418d58a2d46d5f51145b806127a457506001600160a01b038216734fabb145d64652a948d72533023f6e7a623c7c53145b806127cb57506001600160a01b038216731456688345527be1f37e9e627da0837d6f08c925145b806127f257506001600160a01b03821673853d955acef822db058eb8505911ed77f175b99e145b8061281957506001600160a01b03821673bc6da0fe9ad5f3b0d58160288917aa56653660e9145b8061284057506001600160a01b038216735f98805a4e8be255a32880fdec7f6728c6568ba0145b80610a715750506001600160a01b031673674c6ad92fd080e4004b2312b45f796a192d27a01490565b60006001600160a01b038716736b175474e89094c44da98b954eedeac495271d0f148015906128b557506001600160a01b03871673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4814155b80156128de57506001600160a01b03871673dac17f958d2ee523a2206206994597c13d831ec714155b15612a06576128f86001600160a01b0388168460006132f8565b61290c6001600160a01b03881684886132f8565b6000836001600160a01b0316836040518082805190602001908083835b602083106129485780518252601f199092019160209182019101612929565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146129aa576040519150601f19603f3d011682016040523d82523d6000602084013e6129af565b606091505b50509050806129ed576040805162461bcd60e51b8152602060048201526005602482015264021737761760dc1b604482015290519081900360640190fd5b73a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489750505b6001600160a01b03871673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb481415612a3357506001612a5c565b6001600160a01b03871673dac17f958d2ee523a2206206994597c13d831ec71415612a5c575060025b600080730ac00355f80e289f53bf368c9bdb70f5c114c44b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015612aac57600080fd5b505afa158015612ac0573d6000803e3d6000fd5b505050506040513d6020811015612ad657600080fd5b5051604080516370a0823160e01b815230600482015290519192506000916001600160a01b038c16916370a08231916024808301926020929190829003018186803b158015612b2457600080fd5b505afa158015612b38573d6000803e3d6000fd5b505050506040513d6020811015612b4e57600080fd5b505190506000805b8951811015612bda57612b91670de0b6b3a76400006104d58b8481518110612b7a57fe5b602002602001015186611fdd90919063ffffffff16565b9150612bb28c8b8381518110612ba357fe5b602002602001015184896134b8565b612bd0848b8381518110612bc257fe5b60200260200101518761425b565b9450600101612b56565b50730ac00355f80e289f53bf368c9bdb70f5c114c44b6001600160a01b031663a0712d68856040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015612c3557600080fd5b505af1158015612c49573d6000803e3d6000fd5b505050505050505050505050505050565b6001600160a01b03821673df5e0e81dff6faf3a7e52ba697820c5e32d806a81480612ca157506001600160a01b03821673c25a3a3b969415c80451098fa907ec722572917f145b80612cc857506001600160a01b038216733b3ac5386837dc563660fb6a0937dfaa5924333b145b15612e005773bbc81d23ea2c3ec7e56d39296f0cbb648873a5d36001600160a01b03831673c25a3a3b969415c80451098fa907ec722572917f1415612d22575073fcba3e75865d2d561be8d220616520c171f12851612d5e565b6001600160a01b038316733b3ac5386837dc563660fb6a0937dfaa5924333b1415612d5e575073b6c057591e073249f2d9d88ba59a46cfc9b59edb5b612d736001600160a01b0384168260006132f8565b612d876001600160a01b03841682846132f8565b6040805163517a55a360e01b815260048101849052600160248201526000604482018190526064820181905291516001600160a01b0384169263517a55a3926084808201939182900301818387803b158015612de257600080fd5b505af1158015612df6573d6000803e3d6000fd5b5050505050611cb5565b6001600160a01b038216737eb40e450b9655f4b3cc4259bcc731c63ff55ae61480612e4757506001600160a01b038216734f3e8f405cf5afc05d68142f3783bdfe13811522145b80612e6e57506001600160a01b038216733a664ab939fd8482048609f652f9a0b0677337b9145b80612e9557506001600160a01b038216731aef73d49dedc4b1778d0706583995958dc862e6145b80612ebc57506001600160a01b0382167394e131324b6054c0d789b190b2dac504e4361b53145b1561304f5773094d12e5b541784701fd8d65f11fc0598fbc63326001600160a01b038316737eb40e450b9655f4b3cc4259bcc731c63ff55ae61415612f165750733c8caee4e09296800f8d29a68fa3837e2dae4940612fd2565b6001600160a01b038316733a664ab939fd8482048609f652f9a0b0677337b91415612f5657507361e10659fe3aa93d036d099405224e4ac24996d0612fd2565b6001600160a01b038316731aef73d49dedc4b1778d0706583995958dc862e61415612f96575073803a2b40c5a9bb2b86dd630b274fa2a9202874c2612fd2565b6001600160a01b0383167394e131324b6054c0d789b190b2dac504e4361b531415612fd2575073b0a0716841f2fc03fba72a891b8bb13584f52f2d5b612fe76001600160a01b0384168260006132f8565b612ffb6001600160a01b03841682846132f8565b60408051630d2680e960e11b8152600481018490526002602482015260006044820181905291516001600160a01b03841692631a4d01d2926064808201939182900301818387803b158015612de257600080fd5b6001600160a01b038216735282a4ef67d9c33135340fb3289cc1711c13638c141561314b5761309d6001600160a01b038316732dded6da1bf5dbdf597c45fcfaa3194e53ecfeaf60006132f8565b6130c56001600160a01b038316732dded6da1bf5dbdf597c45fcfaa3194e53ecfeaf836132f8565b6040805163517a55a360e01b81526004810183905260016024820181905260006044830181905260648301919091529151732dded6da1bf5dbdf597c45fcfaa3194e53ecfeaf9263517a55a3926084808201939182900301818387803b15801561312e57600080fd5b505af1158015613142573d6000803e3d6000fd5b50505050611cb5565b6001600160a01b038216736c3f90f043a72fa612cbac8115ee7e52bde6e49014156132025773bebc44782c7db0a1a60cb6fe97d0b483032ff1c761319a6001600160a01b0384168260006132f8565b6131ae6001600160a01b03841682846132f8565b60408051630d2680e960e11b8152600481018490526001602482015260006044820181905291516001600160a01b03841692631a4d01d2926064808201939182900301818387803b158015612de257600080fd5b61322b6001600160a01b03831673a79828df1850e8a3a3064576f380d90aecdd335960006132f8565b6132536001600160a01b03831673a79828df1850e8a3a3064576f380d90aecdd3359836132f8565b60408051631e700cbb60e01b81526001600160a01b03841660048201526024810183905260026044820152600060648201819052306084830152915173a79828df1850e8a3a3064576f380d90aecdd335992631e700cbb9260a480820193602093909283900390910190829087803b1580156132ce57600080fd5b505af11580156132e2573d6000803e3d6000fd5b505050506040513d602081101561253a57600080fd5b80158061337e575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b15801561335057600080fd5b505afa158015613364573d6000803e3d6000fd5b505050506040513d602081101561337a57600080fd5b5051155b6133b95760405162461bcd60e51b815260040180806020018281038252603681526020018061469f6036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b1790526126659084905b606061345c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166144019092919063ffffffff16565b8051909150156126655780806020019051602081101561347b57600080fd5b50516126655760405162461bcd60e51b815260040180806020018281038252602a815260200180614675602a913960400191505060405180910390fd5b60006134c26145d1565b60405180608001604052806000815260200160008152602001600081526020016000815250905073a5ca62d95d24a4a350983d5b8ac4eb86388873966001600160a01b0316856001600160a01b031614156136d4576135406001600160a01b03871673a5407eae9ba41422680e2e00537571bcc53efbfd60006132f8565b6135686001600160a01b03871673a5407eae9ba41422680e2e00537571bcc53efbfd866132f8565b60408051630f7c084960e21b8152600f85900b60048201526003602482015260448101869052600060648201819052915173a5407eae9ba41422680e2e00537571bcc53efbfd92633df02124926084808201939182900301818387803b1580156135d157600080fd5b505af11580156135e5573d6000803e3d6000fd5b5050604080516370a0823160e01b815230600482015290517357ab1ec28d129707052df4df418d58a2d46d5f5193506370a0823192506024808301926020929190829003018186803b15801561363a57600080fd5b505afa15801561364e573d6000803e3d6000fd5b505050506040513d602081101561366457600080fd5b5051915061369c7357ab1ec28d129707052df4df418d58a2d46d5f5173a5ca62d95d24a4a350983d5b8ac4eb863888739660006132f8565b6136cf7357ab1ec28d129707052df4df418d58a2d46d5f5173a5ca62d95d24a4a350983d5b8ac4eb8638887396846132f8565b6141ec565b6001600160a01b038516734b5bfd52124784745c1071dcb244c6688d2533d3148061371b57506001600160a01b038516735a770dbd3ee6baf2802d29a901ef11501c44797a145b8061374257506001600160a01b038516738ee57c05741aa9db947a744e713c15d4d19d8822145b8061376957506001600160a01b038516733b96d491f067912d18563d56858ba7d6ec67a6fa145b8061379057506001600160a01b03851673c4daf3b5e2a9e93861c3fbdd25f1e943b8d87417145b806137b757506001600160a01b0385167330fcf7c6cdfc46ec237783d94fc78553e79d4e9c145b806137de57506001600160a01b038516738cc94ccd0f3841a468184aca3cc478d2148e1757145b8061380557506001600160a01b038516731c6a9783f812b3af3abbf7de64c3cd7cc7d1af44145b15613bcf576000856001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561384557600080fd5b505afa158015613859573d6000803e3d6000fd5b505050506040513d602081101561386f57600080fd5b5051905073bbc81d23ea2c3ec7e56d39296f0cbb648873a5d36001600160a01b038716735a770dbd3ee6baf2802d29a901ef11501c44797a14156138c8575073fcba3e75865d2d561be8d220616520c171f12851613a67565b6001600160a01b038716738ee57c05741aa9db947a744e713c15d4d19d88221415613908575073b6c057591e073249f2d9d88ba59a46cfc9b59edb613a67565b6001600160a01b038716733b96d491f067912d18563d56858ba7d6ec67a6fa141561394f5773094d12e5b541784701fd8d65f11fc0598fbc63329050600185019450613a67565b6001600160a01b03871673c4daf3b5e2a9e93861c3fbdd25f1e943b8d87417141561399657733c8caee4e09296800f8d29a68fa3837e2dae49409050600185019450613a67565b6001600160a01b0387167330fcf7c6cdfc46ec237783d94fc78553e79d4e9c14156139dd577361e10659fe3aa93d036d099405224e4ac24996d09050600185019450613a67565b6001600160a01b038716738cc94ccd0f3841a468184aca3cc478d2148e17571415613a245773803a2b40c5a9bb2b86dd630b274fa2a9202874c29050600185019450613a67565b6001600160a01b038716731c6a9783f812b3af3abbf7de64c3cd7cc7d1af441415613a675773b0a0716841f2fc03fba72a891b8bb13584f52f2d90506001850194505b85838660048110613a7457fe5b6020020152613a8e6001600160a01b0389168260006132f8565b613aa26001600160a01b03891682886132f8565b60405162a6cbcd60e21b81526001600160a01b0382169063029b2f3490859060009060040180836080808383875b83811015613ae8578181015183820152602001613ad0565b5050505090500182815260200192505050600060405180830381600087803b158015613b1357600080fd5b505af1158015613b27573d6000803e3d6000fd5b5050604080516370a0823160e01b815230600482015290516001600160a01b03861693506370a0823192506024808301926020929190829003018186803b158015613b7157600080fd5b505afa158015613b85573d6000803e3d6000fd5b505050506040513d6020811015613b9b57600080fd5b50519350613bb46001600160a01b0383168860006132f8565b613bc86001600160a01b03831688866132f8565b50506141ec565b6001600160a01b0385167384e13785b5a27879921d6f685f041421c7f482da1480613c1657506001600160a01b0385167327b7b1ad7288079a66d12350c828d3c00a6f07d7145b15613f28576000856001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b158015613c5657600080fd5b505afa158015613c6a573d6000803e3d6000fd5b505050506040513d6020811015613c8057600080fd5b50519050613c8c6145ef565b604051806060016040528060008152602001600081526020016000815250905085818660038110613cb957fe5b602002015273bebc44782c7db0a1a60cb6fe97d0b483032ff1c76001600160a01b0388167327b7b1ad7288079a66d12350c828d3c00a6f07d71415613d0f5750732dded6da1bf5dbdf597c45fcfaa3194e53ecfeaf5b613d246001600160a01b038a168260006132f8565b613d386001600160a01b038a1682896132f8565b6001600160a01b0388167384e13785b5a27879921d6f685f041421c7f482da1415613dec57604051634515cef360e01b81526001600160a01b03821690634515cef390849060009060040180836060808383875b83811015613da4578181015183820152602001613d8c565b5050505090500182815260200192505050600060405180830381600087803b158015613dcf57600080fd5b505af1158015613de3573d6000803e3d6000fd5b50505050613e83565b6040516315b74c9d60e11b81526001600160a01b03821690632b6e993a90849060009060019060040180846060808383885b83811015613e36578181015183820152602001613e1e565b5050505090500183815260200182151581526020019350505050600060405180830381600087803b158015613e6a57600080fd5b505af1158015613e7e573d6000803e3d6000fd5b505050505b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b158015613ec957600080fd5b505afa158015613edd573d6000803e3d6000fd5b505050506040513d6020811015613ef357600080fd5b50519450613f0c6001600160a01b0384168960006132f8565b613f206001600160a01b03841689876132f8565b5050506141ec565b6001600160a01b038516736ede7f19df5df6ef23bd5b9cedb651580bdf56ca1480613f6f57506001600160a01b03851673b4ada607b9d6b2c9ee07a275e9616b84ac560139145b80613f9657506001600160a01b03851673a74d4b67b3368e83797a35382afb776baae4f5c8145b80613fbd57506001600160a01b038516735fa5b62c8af877cb37031e0a3b2f34a78e3c56a6145b156141ec576000856001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b158015613ffd57600080fd5b505afa158015614011573d6000803e3d6000fd5b505050506040513d602081101561402757600080fd5b505190508482600186016004811061403b57fe5b60200201526140696001600160a01b03881673a79828df1850e8a3a3064576f380d90aecdd335960006132f8565b6140916001600160a01b03881673a79828df1850e8a3a3064576f380d90aecdd3359876132f8565b60405163384e03db60e01b81526001600160a01b0382166004820190815273a79828df1850e8a3a3064576f380d90aecdd33599163384e03db9184918691600091602401836080808383875b838110156140f55781810151838201526020016140dd565b505050509050018281526020019350505050602060405180830381600087803b15801561412157600080fd5b505af1158015614135573d6000803e3d6000fd5b505050506040513d602081101561414b57600080fd5b5050604080516370a0823160e01b815230600482015290516001600160a01b038316916370a08231916024808301926020929190829003018186803b15801561419357600080fd5b505afa1580156141a7573d6000803e3d6000fd5b505050506040513d60208110156141bd57600080fd5b505192506141d66001600160a01b0382168760006132f8565b6141ea6001600160a01b03821687856132f8565b505b846001600160a01b031663d0e30db06040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561422757600080fd5b505af115801561423b573d6000803e3d6000fd5b505050506040513d602081101561425157600080fd5b5050505050505050565b600080836001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156142ab57600080fd5b505afa1580156142bf573d6000803e3d6000fd5b505050506040513d60208110156142d557600080fd5b5051604080516370a0823160e01b8152730ac00355f80e289f53bf368c9bdb70f5c114c44b600482015290519192506000916001600160a01b038716916370a08231916024808301926020929190829003018186803b15801561433757600080fd5b505afa15801561434b573d6000803e3d6000fd5b505050506040513d602081101561436157600080fd5b5051905061438e6001600160a01b038616730ac00355f80e289f53bf368c9bdb70f5c114c44b60006132f8565b6143b66001600160a01b038616730ac00355f80e289f53bf368c9bdb70f5c114c44b846132f8565b836143d2576143c9816104d58885611fdd565b92505050612036565b60006143e2826104d58986611fdd565b9050848110156143f6579250612036915050565b509295945050505050565b606061134084846000858561441585614527565b614466576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106144a55780518252601f199092019160209182019101614486565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614507576040519150601f19603f3d011682016040523d82523d6000602084013e61450c565b606091505b509150915061451c82828661452d565b979650505050505050565b3b151590565b6060831561453c575081612036565b82511561454c5782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561459657818101518382015260200161457e565b50505050905090810190601f1680156145c35780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b60405180608001604052806004906020820280368337509192915050565b6040518060600160405280600390602082028036833750919291505056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a264697066735822122033743fb3c2c81f206225ae17c7a957755ba167cd8c6bbf0f2897e84d1c4b0dcd64736f6c63430007030033

Deployed Bytecode Sourcemap

110:797:2:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6841:1545:3;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;6841:1545:3;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;8392:1546;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;8392:1546:3;;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;8392:1546:3;;;;;;;;;;;;;;;;;;;;;1710:145:14;;;:::i;:::-;;203:702:2;;;;;;;;;;;;;;;;-1:-1:-1;203:702:2;;;;;;;:::i;1078:85:14:-;;;:::i;:::-;;;;-1:-1:-1;;;;;1078:85:14;;;;;;;;;;;;;;6335:152:3;;;;;;;;;;;;;;;;-1:-1:-1;6335:152:3;-1:-1:-1;;;;;6335:152:3;;:::i;9981:3736::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;9981:3736:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;9981:3736:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;9981:3736:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;9981:3736:3;;;;;;;;-1:-1:-1;9981:3736:3;;-1:-1:-1;;;;;9981:3736:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;9981:3736:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;9981:3736:3;;-1:-1:-1;;;;;9981:3736:3;;;;;;;;-1:-1:-1;9981:3736:3;;;;-1:-1:-1;9981:3736:3;;;;-1:-1:-1;;;;9981:3736:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;9981:3736:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;9981:3736:3;;-1:-1:-1;;;;9981:3736:3;;;;-1:-1:-1;9981:3736:3;:::i;6493:240::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;6493:240:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;6493:240:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;6493:240:3;;-1:-1:-1;6493:240:3;;-1:-1:-1;;;;;6493:240:3:i;2004::14:-;;;;;;;;;;;;;;;;-1:-1:-1;2004:240:14;-1:-1:-1;;;;;2004:240:14;;:::i;6841:1545:3:-;6922:7;6945:18;6957:5;6945:11;:18::i;:::-;6941:154;;;6989:52;7036:4;6989:42;7008:5;-1:-1:-1;;;;;7001:27:3;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;7001:29:3;6989:7;;:11;:42::i;:::-;:46;;:52::i;:::-;6979:62;;7070:5;-1:-1:-1;;;;;7063:19:3;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;7063:21:3;;-1:-1:-1;6941:154:3;-1:-1:-1;;;;;7109:13:3;;3760:42;7109:13;;:33;;-1:-1:-1;;;;;;7126:16:3;;3987:42;7126:16;7109:33;:54;;;-1:-1:-1;;;;;;7146:17:3;;4457:42;7146:17;7109:54;:75;;;-1:-1:-1;;;;;;7167:17:3;;4221:42;7167:17;7109:75;7105:1275;;;3911:42;-1:-1:-1;;;;;7240:16:3;;3987:42;7240:16;7236:230;;;-1:-1:-1;4144:42:3;7236:230;;;-1:-1:-1;;;;;7317:17:3;;4457:42;7317:17;7313:153;;;-1:-1:-1;4537:42:3;7313:153;;;-1:-1:-1;;;;;7397:17:3;;4221:42;7397:17;7393:73;;;-1:-1:-1;4380:42:3;7393:73;7503:3;-1:-1:-1;;;;;7487:43:3;;7531:7;7540:1;7487:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;7487:55:3;;-1:-1:-1;7480:62:3;;-1:-1:-1;7480:62:3;7105:1275;-1:-1:-1;;;;;7563:16:3;;5542:42;7563:16;;:36;;-1:-1:-1;;;;;;7583:16:3;;4613:42;7583:16;7563:36;:56;;;-1:-1:-1;;;;;;7603:16:3;;4846:42;7603:16;7563:56;:76;;;-1:-1:-1;;;;;;7623:16:3;;5079:42;7623:16;7563:76;:95;;;-1:-1:-1;;;;;;7643:15:3;;5311:42;7643:15;7563:95;7559:821;;;5699:42;-1:-1:-1;;;;;7717:16:3;;4613:42;7717:16;7713:300;;;-1:-1:-1;4770:42:3;7713:300;;;-1:-1:-1;;;;;7794:16:3;;4846:42;7794:16;7790:223;;;-1:-1:-1;5003:42:3;7790:223;;;-1:-1:-1;;;;;7871:16:3;;5079:42;7871:16;7867:146;;;-1:-1:-1;5236:42:3;7867:146;;;-1:-1:-1;;;;;7948:15:3;;5311:42;7948:15;7944:69;;;-1:-1:-1;5466:42:3;7944:69;8050:3;-1:-1:-1;;;;;8034:43:3;;8078:7;8087:1;8034:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7559:821;-1:-1:-1;;;;;8110:14:3;;5773:42;8110:14;8106:274;;;8147:67;;;-1:-1:-1;;;8147:67:3;;;;;;;;8206:1;8147:67;;;;;;;;;;;;5850:42;;8147:49;;:67;;;;;;;;;;;;;;5850:42;8147:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;8147:67:3;;-1:-1:-1;8140:74:3;;8106:274;8297:72;;;-1:-1:-1;;;8297:72:3;;-1:-1:-1;;;;;8297:72:3;;;;;;;;;;;;8367:1;8297:72;;;;;;6234:42;;8297:53;;:72;;;;;;;;;;;;;;6234:42;8297:72;;;;;;;;;;8106:274;6841:1545;;;;:::o;8392:1546::-;8480:7;8489;8512:20;8520:11;8512:7;:20::i;:::-;8508:118;;;8566:11;-1:-1:-1;;;;;8556:47:3;;:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;8556:49:3;;-1:-1:-1;8607:7:3;;-1:-1:-1;8548:67:3;;8508:118;8640:24;8652:11;8640;:24::i;:::-;8636:466;;;8680:12;8703:11;-1:-1:-1;;;;;8695:39:3;;:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;8695:41:3;8771:33;;;-1:-1:-1;;;8771:33:3;;;;8695:41;;-1:-1:-1;8750:18:3;;-1:-1:-1;;;;;8771:31:3;;;;;:33;;;;;8695:41;;8771:33;;;;;;;:31;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;8771:33:3;8847:28;;;-1:-1:-1;;;8847:28:3;;;;8771:33;;-1:-1:-1;8818:26:3;;-1:-1:-1;;;;;8847:26:3;;;;;:28;;;;;8771:33;;8847:28;;;;;;;:26;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;8847:28:3;8818:57;;;-1:-1:-1;8908:27:3;;;;;8889:16;;8981:32;;9000:12;;;8981:14;:4;8990;8981:8;:14::i;:32::-;8949:64;-1:-1:-1;9035:10:3;9047:43;9086:3;9047:34;:7;8949:64;9047:11;:34::i;:43::-;9027:64;;;;;;;;;;;8636:466;9160:19;9167:11;9160:6;:19::i;:::-;:47;;;;9183:24;9195:11;9183;:24::i;:::-;9156:133;;;874:42;9237:40;9256:11;9269:7;9237:18;:40::i;:::-;9223:55;;;;;;9156:133;9303:21;9312:11;9303:8;:21::i;:::-;9299:593;;;9350:58;9403:4;9350:48;9369:11;-1:-1:-1;;;;;9362:33:3;;:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;9362:35:3;9350:7;;:11;:48::i;:58::-;9340:68;-1:-1:-1;;;;;;9427:19:3;;1609:42;9427:19;9423:79;;;-1:-1:-1;802:42:3;;-1:-1:-1;9479:7:3;9466:21;;9423:79;-1:-1:-1;;;;;9520:20:3;;1682:42;9520:20;9516:81;;;-1:-1:-1;874:42:3;;-1:-1:-1;9574:7:3;9560:22;;9516:81;-1:-1:-1;;;;;9615:20:3;;1755:42;9615:20;9611:81;;;-1:-1:-1;946:42:3;;-1:-1:-1;9669:7:3;9655:22;;9611:81;-1:-1:-1;;;;;9710:20:3;;1828:42;9710:20;9706:81;;;-1:-1:-1;1018:42:3;;-1:-1:-1;9764:7:3;9750:22;;9706:81;-1:-1:-1;;;;;9805:20:3;;1901:42;9805:20;9801:81;;;-1:-1:-1;1090:42:3;;-1:-1:-1;9859:7:3;9845:22;;9801:81;-1:-1:-1;9910:11:3;;-1:-1:-1;9923:7:3;8392:1546;;;;;;:::o;1710:145:14:-;1301:12;:10;:12::i;:::-;-1:-1:-1;;;;;1290:23:14;:7;:5;:7::i;:::-;-1:-1:-1;;;;;1290:23:14;;1282:68;;;;;-1:-1:-1;;;1282:68:14;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;1282:68:14;;;;;;;;;;;;;;;1816:1:::1;1800:6:::0;;1779:40:::1;::::0;-1:-1:-1;;;;;1800:6:14;;::::1;::::0;1779:40:::1;::::0;1816:1;;1779:40:::1;1846:1;1829:19:::0;;-1:-1:-1;;;;;;1829:19:14::1;::::0;;1710:145::o;203:702:2:-;277:7;316:64;718:42:3;345:10:2;365:4;372:7;316:28;:64::i;:::-;391:30;718:42:3;-1:-1:-1;;;;;427:33:2;;:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;427:35:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;427:35:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;427:35:2;;;;;;;;;;;;-1:-1:-1;427:35:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;427:35:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;427:35:2;;;;;;;;;;;;-1:-1:-1;427:35:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;390:72;;;718:42:3;-1:-1:-1;;;;;472:17:2;;490:7;472:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;537:9;532:170;556:13;:20;552:1;:24;532:170;;;597:94;623:13;637:1;623:16;;;;;;;;;;;;;;648:13;662:1;648:16;;;;;;;;;;;;;;-1:-1:-1;;;;;641:34:2;;684:4;641:49;;;;;;;;;;;;;-1:-1:-1;;;;;641:49:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;641:49:2;597:25;:94::i;:::-;578:3;;532:170;;;-1:-1:-1;729:37:2;;;-1:-1:-1;;;729:37:2;;760:4;729:37;;;;;;711:15;;874:42:3;;729:22:2;;:37;;;;;;;;;;;;;;;874:42:3;729:37:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;729:37:2;;-1:-1:-1;784:19:2;;;;776:41;;;;;-1:-1:-1;;;776:41:2;;;;;;;;;;;;-1:-1:-1;;;776:41:2;;;;;;;;;;;;;;;827:46;874:42:3;853:10:2;865:7;827:25;:46::i;:::-;891:7;203:702;-1:-1:-1;;;;203:702:2:o;1078:85:14:-;1124:7;1150:6;-1:-1:-1;;;;;1150:6:14;1078:85;:::o;6335:152:3:-;1301:12:14;:10;:12::i;:::-;-1:-1:-1;;;;;1290:23:14;:7;:5;:7::i;:::-;-1:-1:-1;;;;;1290:23:14;;1282:68;;;;;-1:-1:-1;;;1282:68:14;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;1282:68:14;;;;;;;;;;;;;;;6400:80:3::1;6428:10;6447:6;-1:-1:-1::0;;;;;6440:24:3::1;;6473:4;6440:39;;;;;;;;;;;;;-1:-1:-1::0;;;;;6440:39:3::1;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;6440:39:3;-1:-1:-1;;;;;6400:27:3;::::1;::::0;:80;:27:::1;:80::i;:::-;6335:152:::0;:::o;9981:3736::-;10358:7;;;10402:133;10426:26;:33;10422:1;:37;10402:133;;;10486:38;10494:26;10521:1;10494:29;;;;;;;;;;;;;;10486:3;:7;;:38;;;;:::i;:::-;10480:44;-1:-1:-1;10461:3:3;;10402:133;;;;10608:4;10601:3;:11;;10594:19;;;;10637:6;10630:3;:13;;10623:21;;;;10687:66;-1:-1:-1;;;;;10687:30:3;;10718:10;10738:4;10745:7;10687:30;:66::i;:::-;10789:14;10797:5;10789:7;:14::i;:::-;10785:2312;;;10819:107;10835:5;10842:7;10851:16;10869:26;10897:11;10910:15;10819;:107::i;:::-;10785:2312;;;10984:15;10993:5;10984:8;:15::i;:::-;10980:2117;;;11022:5;-1:-1:-1;;;;;11015:22:3;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;11053:241:3;;-1:-1:-1;11086:15:3;11119:21;11158:16;11192:26;11236:11;11265:15;11053;:241::i;10980:2117::-;11352:18;11364:5;11352:11;:18::i;:::-;11348:1749;;;11393:5;-1:-1:-1;;;;;11386:22:3;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;11443:21:3;;;-1:-1:-1;;;11443:21:3;;;;11424:16;;-1:-1:-1;;;;;11443:19:3;;;;;:21;;;;;11386:24;;11443:21;;;;;;;;:19;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;11443:21:3;11504:41;;;-1:-1:-1;;;11504:41:3;;11539:4;11504:41;;;;;;11443:21;;-1:-1:-1;11478:68:3;;11443:21;;-1:-1:-1;;;;;11504:26:3;;;;;:41;;;;;11443:21;;11504:41;;;;;;;;:26;:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;11504:41:3;11478:15;:68::i;:::-;11615:37;;;-1:-1:-1;;;11615:37:3;;11646:4;11615:37;;;;;;11560:232;;874:42;;;;11615:22;;:37;;;;;;;;;;;;;;874:42;11615:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;11615:37:3;11560:232;;;11615:37;11560:232;;;;;11756:1;11560:232;;;11670:16;;11704:26;;11756:1;11560:15;:232::i;:::-;11348:1749;;;;11841:18;11853:5;11841:11;:18::i;:::-;11837:1260;;;11891:5;-1:-1:-1;;;;;11883:21:3;;11905:7;11883:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;11883:30:3;:35;11875:62;;;;;-1:-1:-1;;;11875:62:3;;;;;;;;;;;;-1:-1:-1;;;11875:62:3;;;;;;;;;;;;;;;11951:241;11984:15;12017:21;12056:16;12090:26;12134:11;12163:15;11951;:241::i;11837:1260::-;12237:14;12245:5;12237:7;:14::i;:::-;12233:864;;;12267:50;-1:-1:-1;;;;;12267:25:3;;620:42;12315:1;12267:25;:50::i;:::-;12331:56;-1:-1:-1;;;;;12331:25:3;;620:42;12379:7;12331:25;:56::i;:::-;12401:96;;;-1:-1:-1;;;12401:96:3;;-1:-1:-1;;;;;12401:96:3;;;;;;-1:-1:-1;;12401:96:3;;;;12491:4;12401:96;;;;;;620:42;;12401:45;;:96;;;;;;;;;;;;;;-1:-1:-1;620:42:3;12401:96;;;;;;;;;;12233:864;12809:31;12825:5;12832:7;12809:15;:31::i;:::-;12909:37;;;-1:-1:-1;;;12909:37:3;;12940:4;12909:37;;;;;;12854:232;;874:42;;;;12909:22;;:37;;;;;;;;;;;;;;874:42;12909:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;12909:37:3;12854:232;;;12909:37;12854:232;;;;;13050:1;12854:232;;;12964:16;;12998:26;;13050:1;12854:15;:232::i;:::-;13143:36;;;-1:-1:-1;;;13143:36:3;;13173:4;13143:36;;;;;;13125:15;;718:42;;13143:21;;:36;;;;;;;;;;;;;;;718:42;13143:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;13143:36:3;;-1:-1:-1;13197:22:3;;;;13189:44;;;;;-1:-1:-1;;;13189:44:3;;;;;;;;;;;;-1:-1:-1;;;13189:44:3;;;;;;;;;;;;;;;13243:45;718:42;13268:10;13280:7;13243:24;:45::i;:::-;13373:10;13369:317;;;13404:9;13399:187;13423:16;:23;13419:1;:27;13399:187;;;13471:100;13497:16;13514:1;13497:19;;;;;;;;;;;;;;13525:16;13542:1;13525:19;;;;;;;13471:100;13448:3;;13399:187;;;-1:-1:-1;13637:37:3;;;-1:-1:-1;;;13637:37:3;;13668:4;13637:37;;;;;;13599:76;;13625:10;;874:42;;13637:22;;:37;;;;;;;;;;;;;;874:42;13637:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;13637:37:3;874:42;;13599:76;:25;:76::i;:::-;13703:7;9981:3736;-1:-1:-1;;;;;;;;;;;;9981:3736:3:o;6493:240::-;1301:12:14;:10;:12::i;:::-;-1:-1:-1;;;;;1290:23:14;:7;:5;:7::i;:::-;-1:-1:-1;;;;;1290:23:14;;1282:68;;;;;-1:-1:-1;;;1282:68:14;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;1282:68:14;;;;;;;;;;;;;;;6574:9:3::1;6569:158;6593:7;:14;6589:1;:18;6569:158;;;6628:88;6660:10;6679:7;6687:1;6679:10;;;;;;;;;;;;;;-1:-1:-1::0;;;;;6672:28:3::1;;6709:4;6672:43;;;;;;;;;;;;;-1:-1:-1::0;;;;;6672:43:3::1;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;6672:43:3;6635:10;;:7;;6643:1;;6635:10;::::1;;;;;;;;;;;-1:-1:-1::0;;;;;6628:31:3::1;;;:88;;;;;:::i;:::-;6609:3;;6569:158;;;;6493:240:::0;:::o;2004::14:-;1301:12;:10;:12::i;:::-;-1:-1:-1;;;;;1290:23:14;:7;:5;:7::i;:::-;-1:-1:-1;;;;;1290:23:14;;1282:68;;;;;-1:-1:-1;;;1282:68:14;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;1282:68:14;;;;;;;;;;;;;;;-1:-1:-1;;;;;2092:22:14;::::1;2084:73;;;;-1:-1:-1::0;;;2084:73:14::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2193:6;::::0;;2172:38:::1;::::0;-1:-1:-1;;;;;2172:38:14;;::::1;::::0;2193:6;::::1;::::0;2172:38:::1;::::0;::::1;2220:6;:17:::0;;-1:-1:-1;;;;;;2220:17:14::1;-1:-1:-1::0;;;;;2220:17:14;;;::::1;::::0;;;::::1;::::0;;2004:240::o;22956:548:3:-;23016:4;-1:-1:-1;;;;;23040:14:3;;1991:42;23040:14;;:48;;-1:-1:-1;;;;;;23070:18:3;;2077:42;23070:18;23040:48;:83;;;-1:-1:-1;;;;;;23104:19:3;;2154:42;23104:19;23040:83;:117;;;-1:-1:-1;;;;;;23139:18:3;;2230:42;23139:18;23040:117;:151;;;-1:-1:-1;;;;;;23173:18:3;;2306:42;23173:18;23040:151;:185;;;-1:-1:-1;;;;;;23207:18:3;;2382:42;23207:18;23040:185;:220;;;-1:-1:-1;;;;;;23241:19:3;;2459:42;23241:19;23040:220;:254;;;-1:-1:-1;;;;;;23276:18:3;;2535:42;23276:18;23040:254;:288;;;-1:-1:-1;;;;;;23310:18:3;;2611:42;23310:18;23040:288;:323;;;-1:-1:-1;;;;;;23344:19:3;;2762:42;23344:19;23040:323;:355;;;-1:-1:-1;;;;;;23379:16:3;;2685:42;23379:16;23040:355;:389;;;-1:-1:-1;;;;;;23411:18:3;;2914:42;23411:18;23040:389;:422;;;-1:-1:-1;;;;;;23445:17:3;;2989:42;23445:17;23040:422;:456;;;-1:-1:-1;;;;;;23478:18:3;;2838:42;23478:18;23032:465;22956:548;-1:-1:-1;;22956:548:3:o;3538:215:16:-;3596:7;3619:6;3615:20;;-1:-1:-1;3634:1:16;3627:8;;3615:20;3657:5;;;3661:1;3657;:5;:1;3680:5;;;;;:10;3672:56;;;;-1:-1:-1;;;3672:56:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3745:1;3538:215;-1:-1:-1;;;3538:215:16:o;4217:150::-;4275:7;4306:1;4302;:5;4294:44;;;;;-1:-1:-1;;;4294:44:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;4359:1;4355;:5;;;;;;;4217:150;-1:-1:-1;;;4217:150:16:o;24215:178:3:-;24271:4;-1:-1:-1;;;;;24295:14:3;;3074:42;24295:14;;:33;;-1:-1:-1;;;;;;24313:15:3;;3147:42;24313:15;24295:33;:52;;;-1:-1:-1;;;;;;24332:15:3;;3220:42;24332:15;24295:52;:71;;;-1:-1:-1;;;;;;24351:15:3;;3293:42;24351:15;24295:71;:90;;;-1:-1:-1;;;;;;;24370:15:3;3366:42;24370:15;;24215:178::o;24046:163::-;24106:4;-1:-1:-1;;;;;24130:14:3;;3455:42;24130:14;;:33;;-1:-1:-1;;;;;;24148:15:3;;3528:42;24148:15;24130:33;:52;;;-1:-1:-1;;;;;;24167:15:3;;3601:42;24167:15;24130:52;:71;;;-1:-1:-1;;;;;;;24186:15:3;3674:42;24186:15;;24046:163::o;23510:530::-;23565:4;-1:-1:-1;;;;;23589:14:3;;3760:42;23589:14;;:47;;-1:-1:-1;;;;;;23619:17:3;;3987:42;23619:17;23589:47;:81;;;-1:-1:-1;;;;;;23652:18:3;;4221:42;23652:18;23589:81;:114;;;-1:-1:-1;;;;;;23686:17:3;;5926:42;23686:17;23589:114;:147;;;-1:-1:-1;;;;;;23719:17:3;;4613:42;23719:17;23589:147;:180;;;-1:-1:-1;;;;;;23752:17:3;;6001:42;23752:17;23589:180;:214;;;-1:-1:-1;;;;;;23785:18:3;;6077:42;23785:18;23589:214;:247;;;-1:-1:-1;;;;;;23819:17:3;;6152:42;23819:17;23589:247;:281;;;-1:-1:-1;;;;;;23852:18:3;;4457:42;23852:18;23589:281;:314;;;-1:-1:-1;;;;;;23886:17:3;;5542:42;23886:17;23589:314;:347;;;-1:-1:-1;;;;;;23919:17:3;;4846:42;23919:17;23589:347;:380;;;-1:-1:-1;;;;;;23952:17:3;;5079:42;23952:17;23589:380;:412;;;-1:-1:-1;;;;;;23985:16:3;;5311:42;23985:16;23589:412;:443;;;-1:-1:-1;;;;;;;24017:15:3;5773:42;24017:15;;23510:530::o;22771:179::-;22828:4;-1:-1:-1;;;;;22852:14:3;;1609:42;22852:14;;:33;;-1:-1:-1;;;;;;22870:15:3;;1682:42;22870:15;22852:33;:52;;;-1:-1:-1;;;;;;22889:15:3;;1755:42;22889:15;22852:52;:71;;;-1:-1:-1;;;;;;22908:15:3;;1828:42;22908:15;22852:71;:90;;;-1:-1:-1;;;;;;;22927:15:3;1901:42;22927:15;;22771:179::o;598:104:4:-;685:10;598:104;:::o;866:203:15:-;993:68;;;-1:-1:-1;;;;;993:68:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;993:68:15;-1:-1:-1;;;993:68:15;;;966:96;;986:5;;966:19;:96::i;:::-;866:203;;;;:::o;22125:232:3:-;22220:23;22232:10;22220:11;:23::i;:::-;22216:135;;;22259:81;22282:10;-1:-1:-1;;;;;22275:24:3;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;22275:26:3;22303:36;;;-1:-1:-1;;;22303:36:3;;;;;;;;;;-1:-1:-1;;;;;22303:27:3;;;;;:36;;;;;22275:26;;22303:36;;;;;;;-1:-1:-1;22303:27:3;:36;;;;;;;;;;;;;;;;;;;;;;;;;;685:175:15;794:58;;;-1:-1:-1;;;;;794:58:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;794:58:15;-1:-1:-1;;;794:58:15;;;767:86;;787:5;;767:19;:86::i;:::-;685:175;;;:::o;2690::16:-;2748:7;2779:5;;;2802:6;;;;2794:46;;;;;-1:-1:-1;;;2794:46:16;;;;;;;;;;;;;;;;;;;;;;;;;;;22363:402:3;22419:4;-1:-1:-1;;;;;22443:13:3;;802:42;22443:13;;:43;;-1:-1:-1;;;;;;22472:14:3;;874:42;22472:14;22443:43;:73;;;-1:-1:-1;;;;;;22502:14:3;;946:42;22502:14;22443:73;:103;;;-1:-1:-1;;;;;;22532:14:3;;1018:42;22532:14;22443:103;:133;;;-1:-1:-1;;;;;;22562:14:3;;1090:42;22562:14;22443:133;:163;;;-1:-1:-1;;;;;;22592:14:3;;1162:42;22592:14;22443:163;:193;;;-1:-1:-1;;;;;;22622:14:3;;1234:42;22622:14;22443:193;:223;;;-1:-1:-1;;;;;;22652:14:3;;1306:42;22652:14;22443:223;:254;;;-1:-1:-1;;;;;;22682:15:3;;1379:42;22682:15;22443:254;:284;;;-1:-1:-1;;;;;;22713:14:3;;1451:42;22713:14;22443:284;:314;;;-1:-1:-1;;;;;;;22743:14:3;1523:42;22743:14;;22363:402::o;15760:1613::-;16069:14;-1:-1:-1;;;;;16153:13:3;;802:42;16153:13;;;;:31;;-1:-1:-1;;;;;;16170:14:3;;874:42;16170:14;;16153:31;:49;;;;-1:-1:-1;;;;;;16188:14:3;;946:42;16188:14;;16153:49;16149:383;;;16218:42;-1:-1:-1;;;;;16218:26:3;;16245:11;16258:1;16218:26;:42::i;:::-;16274:48;-1:-1:-1;;;;;16274:26:3;;16301:11;16314:7;16274:26;:48::i;:::-;16338:12;16356:11;-1:-1:-1;;;;;16356:16:3;16373:15;16356:33;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;16356:33:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16337:52;;;16411:7;16403:25;;;;;-1:-1:-1;;;16403:25:3;;;;;;;;;;;;-1:-1:-1;;;16403:25:3;;;;;;;;;;;;;;;874:42;16508:13;;16149:383;;-1:-1:-1;;;;;16546:14:3;;874:42;16546:14;16542:116;;;-1:-1:-1;16585:1:3;16542:116;;;-1:-1:-1;;;;;16607:14:3;;946:42;16607:14;16603:55;;;-1:-1:-1;16646:1:3;16603:55;16694:20;16724:17;718:42;-1:-1:-1;;;;;16744:23:3;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;16744:25:3;16799:39;;;-1:-1:-1;;;16799:39:3;;16832:4;16799:39;;;;;;16744:25;;-1:-1:-1;16780:16:3;;-1:-1:-1;;;;;16799:24:3;;;;;:39;;;;;16744:25;;16799:39;;;;;;;:24;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;16799:39:3;;-1:-1:-1;16848:19:3;;16877:427;16901:16;:23;16897:1;:27;16877:427;;;17018:53;17066:4;17018:43;17031:26;17058:1;17031:29;;;;;;;;;;;;;;17018:8;:12;;:43;;;;:::i;:53::-;17004:67;;17085;17103:6;17111:16;17128:1;17111:19;;;;;;;;;;;;;;17132:11;17145:6;17085:17;:67::i;:::-;17216:77;17248:9;17259:16;17276:1;17259:19;;;;;;;;;;;;;;17280:12;17216:31;:77::i;:::-;17201:92;-1:-1:-1;16926:3:3;;16877:427;;;;718:42;-1:-1:-1;;;;;17335:17:3;;17353:12;17335:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15760:1613;;;;;;;;;;;:::o;13758:1996::-;-1:-1:-1;;;;;13872:13:3;;3760:42;13872:13;;:33;;-1:-1:-1;;;;;;13889:16:3;;3987:42;13889:16;13872:33;:54;;;-1:-1:-1;;;;;;13909:17:3;;4221:42;13909:17;13872:54;13868:1880;;;3911:42;-1:-1:-1;;;;;13982:16:3;;3987:42;13982:16;13978:150;;;-1:-1:-1;4144:42:3;13978:150;;;-1:-1:-1;;;;;14059:17:3;;4221:42;14059:17;14055:73;;;-1:-1:-1;4380:42:3;14055:73;14142:33;-1:-1:-1;;;;;14142:25:3;;14168:3;14173:1;14142:25;:33::i;:::-;14189:39;-1:-1:-1;;;;;14189:25:3;;14215:3;14220:7;14189:25;:39::i;:::-;14242:68;;;-1:-1:-1;;;14242:68:3;;;;;;;;14298:1;14242:68;;;;14301:1;14242:68;;;;;;;;;;;;;;-1:-1:-1;;;;;14242:46:3;;;;;:68;;;;;;;;;;;14301:1;14242:46;:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13868:1880;;;;-1:-1:-1;;;;;14331:16:3;;4613:42;14331:16;;:36;;-1:-1:-1;;;;;;14351:16:3;;5542:42;14351:16;14331:36;:56;;;-1:-1:-1;;;;;;14371:16:3;;4846:42;14371:16;14331:56;:76;;;-1:-1:-1;;;;;;14391:16:3;;5079:42;14391:16;14331:76;:95;;;-1:-1:-1;;;;;;14411:15:3;;5311:42;14411:15;14331:95;14327:1421;;;5699:42;-1:-1:-1;;;;;14485:16:3;;4613:42;14485:16;14481:300;;;-1:-1:-1;4770:42:3;14481:300;;;-1:-1:-1;;;;;14562:16:3;;4846:42;14562:16;14558:223;;;-1:-1:-1;5003:42:3;14558:223;;;-1:-1:-1;;;;;14639:16:3;;5079:42;14639:16;14635:146;;;-1:-1:-1;5236:42:3;14635:146;;;-1:-1:-1;;;;;14716:15:3;;5311:42;14716:15;14712:69;;;-1:-1:-1;5466:42:3;14712:69;14795:33;-1:-1:-1;;;;;14795:25:3;;14821:3;14826:1;14795:25;:33::i;:::-;14842:39;-1:-1:-1;;;;;14842:25:3;;14868:3;14873:7;14842:25;:39::i;:::-;14895:61;;;-1:-1:-1;;;14895:61:3;;;;;;;;14951:1;14895:61;;;;14954:1;14895:61;;;;;;;;-1:-1:-1;;;;;14895:46:3;;;;;:61;;;;;;;;;;;14954:1;14895:46;:61;;;;;;;;;;14327:1421;-1:-1:-1;;;;;14977:14:3;;5773:42;14977:14;14973:775;;;15007:39;-1:-1:-1;;;;;15007:25:3;;5850:42;15044:1;15007:25;:39::i;:::-;15060:45;-1:-1:-1;;;;;15060:25:3;;5850:42;15097:7;15060:25;:45::i;:::-;15119:73;;;-1:-1:-1;;;15119:73:3;;;;;;;;15181:1;15119:73;;;;;;15184:1;15119:73;;;;;;;;;;;;;;;5850:42;;15119:52;;:73;;;;;;;;;;;15184:1;5850:42;15119:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14973:775;;;-1:-1:-1;;;;;15213:17:3;;4457:42;15213:17;15209:539;;;4537:42;15287:33;-1:-1:-1;;;;;15287:25:3;;4537:42;15246:11;15287:25;:33::i;:::-;15334:39;-1:-1:-1;;;;;15334:25:3;;15360:3;15365:7;15334:25;:39::i;:::-;15387:61;;;-1:-1:-1;;;15387:61:3;;;;;;;;15443:1;15387:61;;;;15446:1;15387:61;;;;;;;;-1:-1:-1;;;;;15387:46:3;;;;;:61;;;;;;;;;;;15446:1;15387:46;:61;;;;;;;;;;15209:539;15524:43;-1:-1:-1;;;;;15524:25:3;;6234:42;15565:1;15524:25;:43::i;:::-;15581:49;-1:-1:-1;;;;;15581:25:3;;6234:42;15622:7;15581:25;:49::i;:::-;15644:93;;;-1:-1:-1;;;15644:93:3;;-1:-1:-1;;;;;15644:93:3;;;;;;;;;;;;15717:1;15644:93;;;;15720:1;15644:93;;;;;;15731:4;15644:93;;;;;;6234:42;;15644:56;;:93;;;;;;;;;;;;;;;;;;6234:42;15644:93;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1329:613:15;1694:10;;;1693:62;;-1:-1:-1;1710:39:15;;;-1:-1:-1;;;1710:39:15;;1734:4;1710:39;;;;-1:-1:-1;;;;;1710:39:15;;;;;;;;;:15;;;;;;:39;;;;;;;;;;;;;;;:15;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1710:39:15;:44;1693:62;1685:150;;;;-1:-1:-1;;;1685:150:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1872:62;;;-1:-1:-1;;;;;1872:62:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1872:62:15;-1:-1:-1;;;1872:62:15;;;1845:90;;1865:5;;2948:751;3367:23;3393:69;3421:4;3393:69;;;;;;;;;;;;;;;;;3401:5;-1:-1:-1;;;;;3393:27:15;;;:69;;;;;:::i;:::-;3476:17;;3367:95;;-1:-1:-1;3476:21:15;3472:221;;3616:10;3605:30;;;;;;;;;;;;;;;-1:-1:-1;3605:30:15;3597:85;;;;-1:-1:-1;;;3597:85:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18216:3903:3;18377:11;18398:33;;:::i;:::-;:84;;;;;;;;18443:1;18398:84;;;;18455:1;18398:84;;;;18467:1;18398:84;;;;18479:1;18398:84;;;;;1901:42;-1:-1:-1;;;;;18497:17:3;:8;-1:-1:-1;;;;;18497:17:3;;18493:3583;;;18530:46;-1:-1:-1;;;;;18530:30:3;;4066:42;18574:1;18530:30;:46::i;:::-;18590:52;-1:-1:-1;;;;;18590:30:3;;4066:42;18634:7;18590:30;:52::i;:::-;18657:69;;;-1:-1:-1;;;18657:69:3;;;;;;;;;;18712:1;18657:69;;;;;;;;;;18724:1;18657:69;;;;;;;;4066:42;;18657:32;;:69;;;;;;;;;;;18724:1;4066:42;18657:69;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;18747:37:3;;;-1:-1:-1;;;18747:37:3;;18778:4;18747:37;;;;;;1090:42;;-1:-1:-1;18747:22:3;;-1:-1:-1;18747:37:3;;;;;;;;;;;;;;1090:42;18747:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;18747:37:3;;-1:-1:-1;18798:34:3;1090:42;1901;18830:1;18798:24;:34::i;:::-;18846:36;1090:42;1901;18878:3;18846:24;:36::i;:::-;18493:3583;;;-1:-1:-1;;;;;18947:16:3;;1991:42;18947:16;;:52;;-1:-1:-1;;;;;;18979:20:3;;2077:42;18979:20;18947:52;:89;;;-1:-1:-1;;;;;;19015:21:3;;2154:42;19015:21;18947:89;:125;;;-1:-1:-1;;;;;;19052:20:3;;2611:42;19052:20;18947:125;:161;;;-1:-1:-1;;;;;;19088:20:3;;2306:42;19088:20;18947:161;:197;;;-1:-1:-1;;;;;;19124:20:3;;2838:42;19124:20;18947:197;:233;;;-1:-1:-1;;;;;;19160:20:3;;2914:42;19160:20;18947:233;:268;;;-1:-1:-1;;;;;;19196:19:3;;2989:42;19196:19;18947:268;18930:3146;;;19240:16;19266:8;-1:-1:-1;;;;;19259:22:3;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;19259:24:3;;-1:-1:-1;3911:42:3;-1:-1:-1;;;;;19337:20:3;;2077:42;19337:20;19333:736;;;-1:-1:-1;4144:42:3;19333:736;;;-1:-1:-1;;;;;19418:21:3;;2154:42;19418:21;19414:655;;;-1:-1:-1;4380:42:3;19414:655;;;-1:-1:-1;;;;;19501:20:3;;2611:42;19501:20;19497:572;;;5699:42;19541:16;;19591:1;19575:17;;;;19497:572;;;-1:-1:-1;;;;;19617:20:3;;2306:42;19617:20;19613:456;;;4770:42;19657:16;;19707:1;19691:17;;;;19613:456;;;-1:-1:-1;;;;;19733:20:3;;2838:42;19733:20;19729:340;;;5003:42;19773:16;;19823:1;19807:17;;;;19729:340;;;-1:-1:-1;;;;;19849:20:3;;2914:42;19849:20;19845:224;;;5236:42;19889:16;;19939:1;19923:17;;;;19845:224;;;-1:-1:-1;;;;;19965:19:3;;2989:42;19965:19;19961:108;;;5466:42;20004:15;;20053:1;20037:17;;;;19961:108;20115:7;20083:15;20099:12;20083:29;;;;;;;;;;:39;20136:38;-1:-1:-1;;;;;20136:30:3;;20167:3;20172:1;20136:30;:38::i;:::-;20188:44;-1:-1:-1;;;;;20188:30:3;;20219:3;20224:7;20188:30;:44::i;:::-;20246:54;;-1:-1:-1;;;20246:54:3;;-1:-1:-1;;;;;20246:34:3;;;;;20281:15;;20298:1;;20246:54;;;20281:15;20246:54;;;20281:15;20298:1;20246:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;20321:41:3;;;-1:-1:-1;;;20321:41:3;;20356:4;20321:41;;;;;;-1:-1:-1;;;;;20321:26:3;;;-1:-1:-1;20321:26:3;;-1:-1:-1;20321:41:3;;;;;;;;;;;;;;:26;:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;20321:41:3;;-1:-1:-1;20376:41:3;-1:-1:-1;;;;;20376:28:3;;20405:8;20415:1;20376:28;:41::i;:::-;20431:43;-1:-1:-1;;;;;20431:28:3;;20460:8;20470:3;20431:28;:43::i;:::-;18930:3146;;;;;-1:-1:-1;;;;;20495:21:3;;2762:42;20495:21;;:43;;-1:-1:-1;;;;;;20520:18:3;;2685:42;20520:18;20495:43;20491:1585;;;20554:16;20580:8;-1:-1:-1;;;;;20573:22:3;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;20573:24:3;;-1:-1:-1;20612:33:3;;:::i;:::-;:72;;;;;;;;20657:1;20612:72;;;;20669:1;20612:72;;;;20681:1;20612:72;;;;;20730:7;20698:15;20714:12;20698:29;;;;;;;;;;:39;4537:42;-1:-1:-1;;;;;20796:18:3;;2685:42;20796:18;20792:72;;;-1:-1:-1;5850:42:3;20792:72;20878:38;-1:-1:-1;;;;;20878:30:3;;20909:3;20914:1;20878:30;:38::i;:::-;20930:44;-1:-1:-1;;;;;20930:30:3;;20961:3;20966:7;20930:30;:44::i;:::-;-1:-1:-1;;;;;20993:21:3;;2762:42;20993:21;20989:213;;;21034:54;;-1:-1:-1;;;21034:54:3;;-1:-1:-1;;;;;21034:34:3;;;;;21069:15;;21086:1;;21034:54;;;21069:15;21034:54;;;21069:15;21086:1;21034:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20989:213;;;21127:60;;-1:-1:-1;;;21127:60:3;;-1:-1:-1;;;;;21127:34:3;;;;;21162:15;;21179:1;;21182:4;;21127:60;;;21162:15;21127:60;;;21162:15;21179:1;21127:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20989:213;21222:41;;;-1:-1:-1;;;21222:41:3;;21257:4;21222:41;;;;;;-1:-1:-1;;;;;21222:26:3;;;;;:41;;;;;;;;;;;;;;:26;:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;21222:41:3;;-1:-1:-1;21277:41:3;-1:-1:-1;;;;;21277:28:3;;21306:8;21316:1;21277:28;:41::i;:::-;21332:43;-1:-1:-1;;;;;21332:28:3;;21361:8;21371:3;21332:28;:43::i;:::-;20491:1585;;;;;;-1:-1:-1;;;;;21426:20:3;;2230:42;21426:20;;:44;;-1:-1:-1;;;;;;21450:20:3;;2382:42;21450:20;21426:44;:69;;;-1:-1:-1;;;;;;21474:21:3;;2459:42;21474:21;21426:69;:93;;;-1:-1:-1;;;;;;21499:20:3;;2535:42;21499:20;21426:93;21422:654;;;21571:16;21597:8;-1:-1:-1;;;;;21590:22:3;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;21590:24:3;;-1:-1:-1;21665:7:3;21629:15;21660:1;21645:16;;21629:33;;;;;;;;;;:43;21686:48;-1:-1:-1;;;;;21686:30:3;;6234:42;21732:1;21686:30;:48::i;:::-;21748:54;-1:-1:-1;;;;;21748:30:3;;6234:42;21794:7;21748:30;:54::i;:::-;21817:74;;-1:-1:-1;;;21817:74:3;;-1:-1:-1;;;;;21817:74:3;;;;;;;;6234:42;;21817:44;;21862:8;;21872:15;;21889:1;;21817:74;;21872:15;21817:74;;;21872:15;21889:1;21817:74;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;21912:41:3;;;-1:-1:-1;;;21912:41:3;;21947:4;21912:41;;;;;;-1:-1:-1;;;;;21912:26:3;;;;;:41;;;;;21817:74;;21912:41;;;;;;;:26;:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;21912:41:3;;-1:-1:-1;21967:41:3;-1:-1:-1;;;;;21967:28:3;;21996:8;22006:1;21967:28;:41::i;:::-;22022:43;-1:-1:-1;;;;;22022:28:3;;22051:8;22061:3;22022:28;:43::i;:::-;21422:654;;22093:8;-1:-1:-1;;;;;22086:24:3;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;18216:3903:3:o;17379:831::-;17543:7;17562:11;17583:16;-1:-1:-1;;;;;17576:34:3;;17619:4;17576:49;;;;;;;;;;;;;-1:-1:-1;;;;;17576:49:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;17576:49:3;17652:39;;;-1:-1:-1;;;17652:39:3;;718:42;17652:39;;;;;;17576:49;;-1:-1:-1;17635:14:3;;-1:-1:-1;;;;;17652:34:3;;;;;:39;;;;;17576:49;;17652:39;;;;;;;:34;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;17652:39:3;;-1:-1:-1;17702:44:3;-1:-1:-1;;;;;17702:36:3;;718:42;17744:1;17702:36;:44::i;:::-;17756:46;-1:-1:-1;;;;;17756:36:3;;718:42;17798:3;17756:36;:46::i;:::-;17949:19;17945:93;;17991:36;18020:6;17991:24;:15;18011:3;17991:19;:24::i;:36::-;17984:43;;;;;;17945:93;18048:12;18063:36;18092:6;18063:24;:15;18083:3;18063:19;:24::i;:36::-;18048:51;;18120:14;18113:4;:21;18109:63;;;18157:4;-1:-1:-1;18150:11:3;;-1:-1:-1;;18150:11:3;18109:63;-1:-1:-1;18189:14:3;;17379:831;-1:-1:-1;;;;;17379:831:3:o;3581:193:1:-;3684:12;3715:52;3737:6;3745:4;3751:1;3754:12;3684;4858:18;4869:6;4858:10;:18::i;:::-;4850:60;;;;;-1:-1:-1;;;4850:60:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;4981:12;4995:23;5022:6;-1:-1:-1;;;;;5022:11:1;5042:5;5050:4;5022:33;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;5022:33:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4980:75;;;;5072:52;5090:7;5099:10;5111:12;5072:17;:52::i;:::-;5065:59;4608:523;-1:-1:-1;;;;;;;4608:523:1:o;726:413::-;1086:20;1124:8;;;726:413::o;7091:725::-;7206:12;7234:7;7230:580;;;-1:-1:-1;7264:10:1;7257:17;;7230:580;7375:17;;:21;7371:429;;7633:10;7627:17;7693:15;7680:10;7676:2;7672:19;7665:44;7582:145;7772:12;7765:20;;-1:-1:-1;;;7765:20:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o

Swarm Source

ipfs://33743fb3c2c81f206225ae17c7a957755ba167cd8c6bbf0f2897e84d1c4b0dcd

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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