ETH Price: $3,452.70 (-1.82%)
Gas: 4 Gwei

Contract

0x1f316C385a5249c83f48061DE45E691ACDc98F06
 
Transaction Hash
Method
Block
From
To
Burn To ETH138869122021-12-27 11:04:54938 days ago1640603094IN
0x1f316C38...ACDc98F06
0 ETH0.0041892840.76444116
Burn To ETH138865822021-12-27 9:48:54938 days ago1640598534IN
0x1f316C38...ACDc98F06
0 ETH0.0043581742.40785558
Burn To ETH138865172021-12-27 9:33:15938 days ago1640597595IN
0x1f316C38...ACDc98F06
0 ETH0.004345842.28257247
Burn To ETH138864612021-12-27 9:21:03938 days ago1640596863IN
0x1f316C38...ACDc98F06
0 ETH0.0043334642.17239969
Burn To ETH138864222021-12-27 9:14:01938 days ago1640596441IN
0x1f316C38...ACDc98F06
0 ETH0.0036046335.07547979
Burn To ETH138864052021-12-27 9:11:46938 days ago1640596306IN
0x1f316C38...ACDc98F06
0 ETH0.003947738.41375558
Burn To ETH138863722021-12-27 9:05:16938 days ago1640595916IN
0x1f316C38...ACDc98F06
0 ETH0.0036213435.23801405
Burn To ETH138861282021-12-27 8:14:21938 days ago1640592861IN
0x1f316C38...ACDc98F06
0 ETH0.0037460736.45178505
Burn To ETH137510282021-12-06 7:44:24959 days ago1638776664IN
0x1f316C38...ACDc98F06
0 ETH0.0099305296.61919371
Burn To ETH137510242021-12-06 7:43:19959 days ago1638776599IN
0x1f316C38...ACDc98F06
0 ETH0.0076733574.6580901
Burn To ETH137008402021-11-28 6:32:40967 days ago1638081160IN
0x1f316C38...ACDc98F06
0 ETH0.0053473652.03332759
Burn To ETH135338152021-11-01 22:17:19994 days ago1635805039IN
0x1f316C38...ACDc98F06
0 ETH0.46196598141.66229521
Burn To ETH135337842021-11-01 22:10:53994 days ago1635804653IN
0x1f316C38...ACDc98F06
0 ETH0.29075523161.0369316
Deposit135336712021-11-01 21:46:29994 days ago1635803189IN
0x1f316C38...ACDc98F06
0 ETH0.01751706162
Deposit135336702021-11-01 21:46:26994 days ago1635803186IN
0x1f316C38...ACDc98F06
0 ETH0.00548969162
Burn To ETH134808962021-10-24 15:11:151002 days ago1635088275IN
0x1f316C38...ACDc98F06
0 ETH0.1721533987.6438148
Deposit134807962021-10-24 14:46:471002 days ago1635086807IN
0x1f316C38...ACDc98F06
0 ETH0.0062397565.16166664
Burn To ETH134804692021-10-24 13:30:591002 days ago1635082259IN
0x1f316C38...ACDc98F06
0 ETH0.1372232569.86077182
Deposit134803862021-10-24 13:09:391002 days ago1635080979IN
0x1f316C38...ACDc98F06
0 ETH0.0049246480
Deposit134802732021-10-24 12:43:341002 days ago1635079414IN
0x1f316C38...ACDc98F06
0 ETH0.0045766847.80625948
Deposit134802242021-10-24 12:34:101002 days ago1635078850IN
0x1f316C38...ACDc98F06
0 ETH0.0046259651.39956623
Deposit134660212021-10-22 7:11:551004 days ago1634886715IN
0x1f316C38...ACDc98F06
0 ETH0.0055767461
Burn To ETH134487942021-10-19 14:36:491007 days ago1634654209IN
0x1f316C38...ACDc98F06
0 ETH0.2817168577.40560558
Deposit134486792021-10-19 14:09:191007 days ago1634652559IN
0x1f316C38...ACDc98F06
0 ETH0.0058693864.20102848
Burn To ETH134134522021-10-14 1:32:011013 days ago1634175121IN
0x1f316C38...ACDc98F06
0 ETH0.0036336880
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
135338152021-11-01 22:17:19994 days ago1635805039
0x1f316C38...ACDc98F06
10.6530676 ETH
135338152021-11-01 22:17:19994 days ago1635805039
0x1f316C38...ACDc98F06
10.6530676 ETH
134808962021-10-24 15:11:151002 days ago1635088275
0x1f316C38...ACDc98F06
0 ETH
134808962021-10-24 15:11:151002 days ago1635088275
0x1f316C38...ACDc98F06
0 ETH
134804692021-10-24 13:30:591002 days ago1635082259
0x1f316C38...ACDc98F06
0 ETH
134804692021-10-24 13:30:591002 days ago1635082259
0x1f316C38...ACDc98F06
0 ETH
134487942021-10-19 14:36:491007 days ago1634654209
0x1f316C38...ACDc98F06
98.3396055 ETH
134487942021-10-19 14:36:491007 days ago1634654209
0x1f316C38...ACDc98F06
98.3396055 ETH
134134522021-10-14 1:32:011013 days ago1634175121
0x1f316C38...ACDc98F06
0 ETH
134134522021-10-14 1:32:011013 days ago1634175121
0x1f316C38...ACDc98F06
0 ETH
133839662021-10-09 10:23:531017 days ago1633775033
0x1f316C38...ACDc98F06
10.80574016 ETH
133839662021-10-09 10:23:531017 days ago1633775033
0x1f316C38...ACDc98F06
10.80574016 ETH
133702952021-10-07 6:48:361019 days ago1633589316
0x1f316C38...ACDc98F06
52.34402042 ETH
133702952021-10-07 6:48:361019 days ago1633589316
0x1f316C38...ACDc98F06
52.34402042 ETH
133634072021-10-06 4:50:421020 days ago1633495842
0x1f316C38...ACDc98F06
334.08328656 ETH
133634072021-10-06 4:50:421020 days ago1633495842
0x1f316C38...ACDc98F06
334.08328656 ETH
132572162021-09-19 16:26:411037 days ago1632068801
0x1f316C38...ACDc98F06
10.55944785 ETH
132572162021-09-19 16:26:411037 days ago1632068801
0x1f316C38...ACDc98F06
10.55944785 ETH
132270082021-09-15 0:13:241042 days ago1631664804
0x1f316C38...ACDc98F06
33.12269427 ETH
132270082021-09-15 0:13:241042 days ago1631664804
0x1f316C38...ACDc98F06
33.12269427 ETH
132268742021-09-14 23:40:261042 days ago1631662826
0x1f316C38...ACDc98F06
22.65905613 ETH
132268742021-09-14 23:40:261042 days ago1631662826
0x1f316C38...ACDc98F06
22.65905613 ETH
132266992021-09-14 23:03:421042 days ago1631660622
0x1f316C38...ACDc98F06
5.89301217 ETH
132266992021-09-14 23:03:421042 days ago1631660622
0x1f316C38...ACDc98F06
5.89301217 ETH
131961302021-09-10 5:30:111046 days ago1631251811
0x1f316C38...ACDc98F06
35.7961347 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
DelayedBurner

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 20: DelayedBurner.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.3;
pragma experimental ABIEncoderV2;

import "./IERC20.sol";
import "./SafeERC20.sol";
import "./SafeMath.sol";
import "./AccessControl.sol";

import "./IUniswapV2.sol";
import "./IWETH.sol";
import "./IBasket.sol";

import "./BDIMarketMaker.sol";

contract DelayedBurner is MarketMakerBurner {
    using SafeERC20 for IERC20;
    using SafeMath for uint256;

    // Can only burn after 20 mins, and only has a 20 mins window to burn
    // 20 min window to burn
    uint256 public burnDelaySeconds = 1200;
    uint256 public maxBurnDelaySeconds = 2400;

    // Deployer
    address public governance;

    // User deposited
    mapping(address => uint256) public deposits;

    // When user deposited
    mapping(address => uint256) public timestampWhenDeposited;

    // Blacklist
    mapping(address => bool) public isBlacklisted;

    constructor(address _governance) {
        governance = _governance;

        IERC20(WETH).safeApprove(SUSHISWAP_ROUTER, uint256(-1));
        IERC20(WETH).safeApprove(UNIV2_ROUTER, uint256(-1));
    }

    receive() external payable {}

    // **** Modifiers ****

    modifier onlyGov() {
        require(msg.sender == governance, "!governance");
        _;
    }

    modifier onlyEOA() {
        require(msg.sender == tx.origin, "!eoa");
        _;
    }

    modifier notBlacklisted() {
        require(!isBlacklisted[msg.sender], "blacklisted");
        _;
    }

    // **** Restricted functions ****

    function setGov(address _governance) public onlyGov {
        governance = _governance;
    }

    function rescueERC20(address _token) public onlyGov {
        require(_token != address(BDPI), "!bdpi");
        uint256 _amount = IERC20(_token).balanceOf(address(this));
        IERC20(_token).safeTransfer(governance, _amount);
    }

    function rescueERC20s(address[] memory _tokens) public onlyGov {
        for (uint256 i = 0; i < _tokens.length; i++) {
            rescueERC20(_tokens[i]);
        }
    }

    function setBurnDelaySeconds(uint256 _seconds) public onlyGov {
        burnDelaySeconds = _seconds;
    }

    function setMaxBurnDelaySeconds(uint256 _seconds) public onlyGov {
        maxBurnDelaySeconds = _seconds;
    }

    function setBlacklist(address _user, bool _b) public onlyGov {
        isBlacklisted[_user] = _b;
    }

    // **** Deposit **** //

    function deposit(uint256 _amount) public {
        IERC20(address(BDPI)).safeTransferFrom(msg.sender, address(this), _amount);

        deposits[msg.sender] = deposits[msg.sender].add(_amount);
        timestampWhenDeposited[msg.sender] = block.timestamp;
    }

    // **** Withdraw **** //

    function withdraw(uint256 _amount) public {
        deposits[msg.sender] = deposits[msg.sender].sub(_amount);

        IERC20(address(BDPI)).safeTransfer(msg.sender, _amount);
    }

    // **** Burn **** //

    function burn() public onlyEOA notBlacklisted returns (uint256[] memory) {
        uint256 _amount = deposits[msg.sender];

        require(_amount > 0, "!amount");
        require(_canBurn(timestampWhenDeposited[msg.sender]), "!timestamp");

        deposits[msg.sender] = 0;

        (address[] memory assets, ) = IBasket(BDPI).getAssetsAndBalances();
        uint256[] memory deltas = new uint256[](assets.length);

        for (uint256 i = 0; i < assets.length; i++) {
            deltas[i] = IERC20(assets[i]).balanceOf(address(this));
        }
        IBasket(BDPI).burn(_amount);
        for (uint256 i = 0; i < assets.length; i++) {
            deltas[i] = IERC20(assets[i]).balanceOf(address(this)).sub(deltas[i]);
            IERC20(assets[i]).transfer(msg.sender, deltas[i]);
        }

        return deltas;
    }

    function burnToETH(
        address[] memory routers,
        bytes[] memory routerCalldata,
        address[] memory constituents,
        address[] memory underlyings,
        uint256[] memory underlyingsWeights,
        uint256 _minETHAmount
    ) public onlyEOA notBlacklisted returns (uint256) {
        uint256 _amount = deposits[msg.sender];

        require(_amount > 0, "!amount");
        require(_canBurn(timestampWhenDeposited[msg.sender]), "!timestamp");

        deposits[msg.sender] = 0;

        // Memory
        bytes memory mmParams =
            abi.encode(
                MMParams({
                    routers: routers,
                    routerCalldata: routerCalldata,
                    constituents: constituents,
                    underlyings: underlyings,
                    underlyingsWeights: underlyingsWeights
                })
            );
            
        _burnBDIToWETH(_amount, mmParams);
        uint256 totalWETH = IERC20(WETH).balanceOf(address(this));
        require(totalWETH >= _minETHAmount, "!min-eth-amount");
        IWETH(WETH).withdraw(totalWETH);

        (bool success, ) = msg.sender.call{ value: totalWETH }("");
        require(success, "!eth-transfer");

        return totalWETH;
    }

    // **** Internals **** //

    function _canBurn(uint256 _depositTime) public view returns (bool) {
        return
            block.timestamp >= _depositTime + burnDelaySeconds && block.timestamp <= _depositTime + maxBurnDelaySeconds;
    }
}

File 2 of 20: AccessControl.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./EnumerableSet.sol";
import "./Address.sol";
import "./Context.sol";

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
abstract contract AccessControl is Context {
    using EnumerableSet for EnumerableSet.AddressSet;
    using Address for address;

    struct RoleData {
        EnumerableSet.AddressSet members;
        bytes32 adminRole;
    }

    mapping (bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view returns (bool) {
        return _roles[role].members.contains(account);
    }

    /**
     * @dev Returns the number of accounts that have `role`. Can be used
     * together with {getRoleMember} to enumerate all bearers of a role.
     */
    function getRoleMemberCount(bytes32 role) public view returns (uint256) {
        return _roles[role].members.length();
    }

    /**
     * @dev Returns one of the accounts that have `role`. `index` must be a
     * value between 0 and {getRoleMemberCount}, non-inclusive.
     *
     * Role bearers are not sorted in any particular way, and their ordering may
     * change at any point.
     *
     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
     * you perform all queries on the same block. See the following
     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
     * for more information.
     */
    function getRoleMember(bytes32 role, uint256 index) public view returns (address) {
        return _roles[role].members.at(index);
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) public virtual {
        require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to grant");

        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) public virtual {
        require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to revoke");

        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) public virtual {
        require(account == _msgSender(), "AccessControl: can only renounce roles for self");

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);
        _roles[role].adminRole = adminRole;
    }

    function _grantRole(bytes32 role, address account) private {
        if (_roles[role].members.add(account)) {
            emit RoleGranted(role, account, _msgSender());
        }
    }

    function _revokeRole(bytes32 role, address account) private {
        if (_roles[role].members.remove(account)) {
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}

File 3 of 20: 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 20: BDIMarketMaker.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.7.3;
pragma experimental ABIEncoderV2;

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

import "./IBasket.sol";
import "./IATokenV1.sol";
import "./IUniswapV2.sol";
import "./IComptroller.sol";
import "./ISushiBar.sol";
import "./ICToken.sol";
import "./ICurve.sol";
import "./ILendingPoolV1.sol";
import "./IWETH.sol";
import "./IYearn.sol";

import "./console.sol";

contract MarketMakerHelpers {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    // **** So we dont have to keep passing data through the functions ****

    // Stateful market maker params
    // routers:           Routers used for swapping (e.g. 1inch, Uniswap, Matcha)
    // routerCalldata:    Calldata contract has to use
    // constituents:      BDI constituents tokens (e.g. yvSNX, yvUNI, cCOMP...)
    // underlyings:       Underlyings of constituents (e.g. SNX, UNI, COMP...)
    // underlyingWeghts:  Weightings of the underlyings, (i.e. % they represent in BDI)
    //                    Should add up to 1e18
    struct MMParams {
        address[] routers;
        bytes[] routerCalldata;
        address[] constituents;
        address[] underlyings;
        uint256[] underlyingsWeights;
    }

    // **** Misc ****

    address constant SOLO = 0x1E0447b19BB6EcFdAe1e4AE1694b0C3659614e4e;

    // **** DeFi ****

    // Aave
    address constant LENDING_POOL_V1 = 0x398eC7346DcD622eDc5ae82352F02bE94C62d119;
    address constant LENDING_POOL_CORE_V1 = 0x3dfd23A6c5E8BbcFc9581d2E864a68feb6a076d3;

    // Curve
    address constant CURVE_LINK_POOL = 0xF178C0b5Bb7e7aBF4e12A4838C7b7c5bA2C623c0;

    // Compound
    address constant COMPTROLLER = 0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B;

    // **** Tokens ****

    // Curve Tokens
    address constant linkCRV = 0xcee60cFa923170e4f8204AE08B4fA6A3F5656F3a;
    address constant gaugeLinkCRV = 0xFD4D8a17df4C27c1dD245d153ccf4499e806C87D;

    // Router address
    address constant SUSHISWAP_FACTORY = 0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac;
    address constant SUSHISWAP_ROUTER = 0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F;
    address constant UNIV2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;

    // Yearn
    address constant yvCurveLink = 0xf2db9a7c0ACd427A680D640F02d90f6186E71725;
    address constant yveCRV = 0xc5bDdf9843308380375a611c18B50Fb9341f502A;
    address constant yvBOOST = 0x9d409a0A012CFbA9B15F6D4B36Ac57A46966Ab9a;
    address constant yvUNI = 0xFBEB78a723b8087fD2ea7Ef1afEc93d35E8Bed42;
    address constant yvYFI = 0xE14d13d8B3b85aF791b2AADD661cDBd5E6097Db1;
    address constant yvSNX = 0xF29AE508698bDeF169B89834F76704C3B205aedf;

    // CTokens
    address constant CUNI = 0x35A18000230DA775CAc24873d00Ff85BccdeD550;
    address constant CCOMP = 0x70e36f6BF80a52b3B46b3aF8e106CC0ed743E8e4;

    // SUSHI
    address constant XSUSHI = 0x8798249c2E607446EfB7Ad49eC89dD1865Ff4272;

    // WETH
    address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;

    // BDI
    address constant BDI = 0x0309c98B1bffA350bcb3F9fB9780970CA32a5060;
    address constant SUSHI_BDI_ETH = 0x8d782C5806607E9AAFB2AC38c1DA3838Edf8BD03;

    // Underlyings
    address constant LINK = 0x514910771AF9Ca656af840dff83E8264EcF986CA;
    address constant CRV = 0xD533a949740bb3306d119CC777fa900bA034cd52;
    address constant UNI = 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984;
    address constant COMP = 0xc00e94Cb662C3520282E6f5717214004A7f26888;
    address constant YFI = 0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e;
    address constant SNX = 0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F;
    address constant MKR = 0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2;
    address constant REN = 0x408e41876cCCDC0F92210600ef50372656052a38;
    address constant KNC = 0xdd974D5C2e2928deA5F71b9825b8b646686BD200;
    address constant LRC = 0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD;
    address constant BAL = 0xba100000625a3754423978a60c9317c58a424e3D;
    address constant AAVE = 0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9;
    address constant MTA = 0xa3BeD4E1c75D00fa6f4E5E6922DB7261B5E9AcD2;
    address constant SUSHI = 0x6B3595068778DD592e39A122f4f5a5cF09C90fE2;
    address constant ZRX = 0xE41d2489571d322189246DaFA5ebDe1F4699F498;

    // ATokens v1
    address constant AYFIv1 = 0x12e51E77DAAA58aA0E9247db7510Ea4B46F9bEAd;
    address constant ASNXv1 = 0x328C4c80BC7aCa0834Db37e6600A6c49E12Da4DE;
    address constant AMKRv1 = 0x7deB5e830be29F91E298ba5FF1356BB7f8146998;
    address constant ARENv1 = 0x69948cC03f478B95283F7dbf1CE764d0fc7EC54C;
    address constant AKNCv1 = 0x9D91BE44C06d373a8a226E1f3b146956083803eB;

    // BDPI
    IBasket constant BDPI = IBasket(0x0309c98B1bffA350bcb3F9fB9780970CA32a5060);

    /// @notice Enters Compound market. *Must be called before toCToken*
    /// @param  _markets  Compound markets to enter (underlying, not cTokens)
    function enterMarkets(address[] memory _markets) public {
        IComptroller(COMPTROLLER).enterMarkets(_markets);
    }

    // **** Internal ****

    /// @notice Converts a constituent to its underlying
    /// @param _constituent Derivate token address, if its the underlying it won't do anything
    /// @return Underlying address
    function _toUnderlying(address _constituent, uint256 _amount) internal returns (address, uint256) {
        if (_isCToken(_constituent)) {
            return _fromCToken(_constituent, _amount);
        }

        if (_isATokenV1(_constituent)) {
            return _fromATokenV1(_constituent, _amount);
        }

        if (_constituent == XSUSHI) {
            return _fromXSushi(_amount);
        }

        if (_constituent == linkCRV) {
            return _fromLinkCRV(_amount);
        }

        if (_constituent == gaugeLinkCRV) {
            (, uint256 amount) = _fromGaugeLinkCRV(_amount);
            return _fromLinkCRV(amount);
        }

        if (_constituent == yvCurveLink) {
            (, uint256 amount) = _fromYearnLinkCRV(_amount);
            return _fromLinkCRV(amount);
        }

        if (_constituent == yvBOOST || _constituent == yveCRV) {
            if (_constituent == yveCRV) {
                _toYveBoost();
            }

            // Just sell directly on uniswap
            address[] memory path = new address[](2);
            path[0] = yvBOOST;
            path[1] = WETH;

            uint256 _bamount = IERC20(yvBOOST).balanceOf(address(this));

            IERC20(yvBOOST).approve(SUSHISWAP_ROUTER, _bamount);
            uint256[] memory outs =
                IUniswapV2Router02(SUSHISWAP_ROUTER).swapExactTokensForTokens(
                    _bamount,
                    0,
                    path,
                    address(this),
                    block.timestamp + 60
                );

            return (WETH, outs[1]);
        }

        // Yearn
        if (_constituent == yvCurveLink || _constituent == yvUNI || _constituent == yvYFI || _constituent == yvSNX) {
            (address _yearnUnderlying, uint256 _yearnAmount) = _fromYearnV2Vault(_constituent, _amount);
            return _toUnderlying(_yearnUnderlying, _yearnAmount);
        }

        return (_constituent, _amount);
    }

    /// @notice Converts underlying to constituent
    /// @param  _constituent  Address of the constituent token
    function _toConstituent(address _underlying, address _constituent) internal {
        if (_underlying == _constituent) {
            return;
        }

        if (_isCToken(_constituent)) {
            _toCToken(_underlying);
        } else if (_isATokenV1(_constituent)) {
            _toATokenV1(_underlying);
        } else if (_constituent == XSUSHI) {
            _toXSushi();
        } else if (_underlying == LINK && _constituent == linkCRV) {
            _toLinkCRV();
        } else if (_underlying == LINK && _constituent == yvCurveLink) {
            _toLinkCRV();
            _toYearnLinkCRV();
        } else if (_underlying == LINK && _constituent == gaugeLinkCRV) {
            // Underlying should always be LINK
            // as we cannot get linkCRV on exchanges
            _toLinkCRV();
            _toGaugeLinkCRV();
        } else if (_underlying == CRV && _constituent == yveCRV) {
            // Underlying should always be CRV
            _toYveCRV();
        } else if (_underlying == CRV && _constituent == yvBOOST) {
            // Underlying should always be CRV
            _toYveCRV();
            _toYveBoost();
        } else if (_isYearnV2(_constituent)) {
            // This needs to be after yvCurveLink, yveCRV, and yvBoost
            // As they have a different conversion structure
            _toYearnV2Vault(_constituent);
        }
    }

    /// @notice Checks if a token is aTokenV1
    /// @param  _atoken Token address
    /// @return Boolean value indicating if token is an aTokenV1
    function _isATokenV1(address _atoken) public pure returns (bool) {
        return (_atoken == AYFIv1 || _atoken == ASNXv1 || _atoken == AMKRv1 || _atoken == ARENv1 || _atoken == AKNCv1);
    }

    /// @notice Checks if a token is cToken
    /// @param  _ctoken Token address
    /// @return Boolean value indicating if token is a cToken
    function _isCToken(address _ctoken) public pure returns (bool) {
        return (_ctoken == CCOMP || _ctoken == CUNI);
    }

    /// @notice Checks if a token is cToken
    /// @param  _vault Vault address
    /// @return Boolean value indicating if token is a cToken
    function _isYearnV2(address _vault) public pure returns (bool) {
        return (_vault == yvCurveLink || _vault == yvUNI || _vault == yvYFI || _vault == yvSNX);
    }

    /// @notice Supplies assets to the Compound market
    /// @param  _token  Underlying token to supply to Compound
    function _toCToken(address _token) internal {
        // Only doing UNI or COMP for CTokens
        require(_token == UNI || _token == COMP, "!valid-to-ctoken");

        address _ctoken = _getTokenToCToken(_token);
        uint256 balance = IERC20(_token).balanceOf(address(this));

        require(balance > 0, "!token-bal");

        IERC20(_token).safeApprove(_ctoken, 0);
        IERC20(_token).safeApprove(_ctoken, balance);
        require(ICToken(_ctoken).mint(balance) == 0, "!ctoken-mint");
    }

    /// @notice Redeems assets from the Compound market
    /// @param  _ctoken  CToken to redeem from Compound
    function _fromCToken(address _ctoken, uint256 _camount) internal returns (address _token, uint256 _amount) {
        // Only doing CUNI or CCOMP
        require(_ctoken == CUNI || _ctoken == CCOMP, "!valid-from-ctoken");

        _token = ICToken(_ctoken).underlying();

        uint256 before = IERC20(_token).balanceOf(address(this));
        require(ICToken(_ctoken).redeem(_camount) == 0, "!ctoken-redeem");
        _amount = IERC20(_token).balanceOf(address(this)).sub(before);
    }

    /// @notice Supplies assets to the Aave market
    /// @param  _token  Underlying to supply to Aave
    function _toATokenV1(address _token) internal {
        require(_token != UNI && _token != COMP, "no-uni-or-comp");

        uint256 balance = IERC20(_token).balanceOf(address(this));

        require(balance > 0, "!token-bal");

        IERC20(_token).safeApprove(LENDING_POOL_CORE_V1, 0);
        IERC20(_token).safeApprove(LENDING_POOL_CORE_V1, balance);
        ILendingPoolV1(LENDING_POOL_V1).deposit(_token, balance, 0);
    }

    /// @notice Redeems assets from the Aave market
    /// @param  _atoken  AToken to redeem from Aave
    function _fromATokenV1(address _atoken, uint256 _aamount) internal returns (address _token, uint256 _amount) {
        _token = IATokenV1(_atoken).underlyingAssetAddress();

        uint256 before = IERC20(_token).balanceOf(address(this));
        IATokenV1(_atoken).redeem(_aamount);
        _amount = IERC20(_token).balanceOf(address(this)).sub(before);
    }

    /// @notice Converts link to linkCRV
    function _toLinkCRV() internal {
        // Deposit into gauge
        uint256 balance = IERC20(LINK).balanceOf(address(this));

        IERC20(LINK).safeApprove(CURVE_LINK_POOL, 0);
        IERC20(LINK).safeApprove(CURVE_LINK_POOL, balance);

        ICurveLINK(CURVE_LINK_POOL).add_liquidity([balance, uint256(0)], 0);
    }

    /// @notice Converts linkCRV to link
    function _fromLinkCRV(uint256 _lamount) internal returns (address, uint256) {
        uint256 _before = IERC20(LINK).balanceOf(address(this));
        ICurveLINK(CURVE_LINK_POOL).remove_liquidity_one_coin(_lamount, 0, 0);
        uint256 _after = IERC20(LINK).balanceOf(address(this));
        return (LINK, _after.sub(_before));
    }

    /// @notice Converts linkCRV to GaugeLinkCRV
    function _toGaugeLinkCRV() internal {
        // Deposit into gauge
        uint256 balance = IERC20(linkCRV).balanceOf(address(this));
        IERC20(linkCRV).safeApprove(gaugeLinkCRV, 0);
        IERC20(linkCRV).safeApprove(gaugeLinkCRV, balance);
        ILinkGauge(gaugeLinkCRV).deposit(balance);
    }

    /// @notice Converts GaugeLinkCRV to linkCRV
    function _fromGaugeLinkCRV(uint256 _amount) internal returns (address, uint256) {
        // Deposit into gauge
        uint256 _before = IERC20(linkCRV).balanceOf(address(this));
        ILinkGauge(gaugeLinkCRV).withdraw(_amount);
        uint256 _after = IERC20(linkCRV).balanceOf(address(this));
        return (linkCRV, _after.sub(_before));
    }

    /// @notice Converts from crv to yveCRV
    function _toYveCRV() internal {
        uint256 balance = IERC20(CRV).balanceOf(address(this));
        IERC20(CRV).safeApprove(yveCRV, 0);
        IERC20(CRV).safeApprove(yveCRV, balance);
        IveCurveVault(yveCRV).deposit(balance);
    }

    /// @notice Converts from yveCRV to yvBOOST
    function _toYveBoost() internal {
        uint256 balance = IERC20(yveCRV).balanceOf(address(this));
        IERC20(yveCRV).safeApprove(yvBOOST, 0);
        IERC20(yveCRV).safeApprove(yvBOOST, balance);
        IYearn(yvBOOST).deposit(balance);
    }

    /// @notice Converts from linkCRV to yearnLinkCRV
    function _toYearnLinkCRV() internal {
        uint256 balance = IERC20(linkCRV).balanceOf(address(this));
        IERC20(linkCRV).safeApprove(yvCurveLink, 0);
        IERC20(linkCRV).safeApprove(yvCurveLink, balance);
        IYearn(yvCurveLink).deposit(balance);
    }

    /// @notice Converts from yearnLinkCRV to linkCRV
    function _fromYearnLinkCRV(uint256 _amount) internal returns (address, uint256) {
        uint256 _before = IERC20(linkCRV).balanceOf(address(this));
        IYearn(yvCurveLink).withdraw(_amount);
        uint256 _after = IERC20(linkCRV).balanceOf(address(this));
        return (linkCRV, _after.sub(_before));
    }

    /// @notice Converts from yveCRV to yvBOOST
    function _fromYveBoost(uint256 _amount) internal returns (address, uint256) {
        uint256 _before = IERC20(yveCRV).balanceOf(address(this));
        IYearn(yvBOOST).withdraw(_amount);
        uint256 _after = IERC20(yveCRV).balanceOf(address(this));
        return (yveCRV, _after.sub(_before));
    }

    /// @notice Converts to Yearn Vault
    function _toYearnV2Vault(address _vault) internal {
        address _underlying = IYearn(_vault).token();
        uint256 _amount = IERC20(_underlying).balanceOf(address(this));
        IERC20(_underlying).safeApprove(_vault, 0);
        IERC20(_underlying).safeApprove(_vault, _amount);
        IYearn(_vault).deposit();
    }

    /// @notice Converts from Yearn Vault
    function _fromYearnV2Vault(address _vault, uint256 _amount) internal returns (address, uint256) {
        address _underlying = IYearn(_vault).token();
        uint256 _before = IERC20(_underlying).balanceOf(address(this));
        IYearn(_vault).withdraw(_amount);
        uint256 _after = IERC20(_underlying).balanceOf(address(this));
        return (_underlying, _after.sub(_before));
    }

    /// @dev Token to CToken mapping
    /// @param  _token Token address
    function _getTokenToCToken(address _token) internal pure returns (address) {
        if (_token == UNI) {
            return CUNI;
        }
        if (_token == COMP) {
            return CCOMP;
        }
        revert("!supported-token-to-ctoken");
    }

    /// @notice Converts sushi to xsushi
    function _toXSushi() internal {
        uint256 balance = IERC20(SUSHI).balanceOf(address(this));
        require(balance > 0, "!sushi-bal");

        IERC20(SUSHI).safeApprove(XSUSHI, 0);
        IERC20(SUSHI).safeApprove(XSUSHI, balance);
        ISushiBar(XSUSHI).enter(balance);
    }

    /// @notice Goes from xsushi to sushi
    function _fromXSushi(uint256 _xsushiAmount) internal returns (address, uint256) {
        uint256 before = IERC20(SUSHI).balanceOf(address(this));
        ISushiBar(XSUSHI).leave(_xsushiAmount);
        uint256 delta = IERC20(SUSHI).balanceOf(address(this)).sub(before);
        return (SUSHI, delta);
    }
}

contract MarketMakerMinter is MarketMakerHelpers {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    /// @notice Converts ETH into BDI
    function _mintBDIWithWETH(uint256 _wethAmount, bytes memory _mmData) internal returns (uint256) {
        MMParams memory mmParams = abi.decode(_mmData, (MMParams));

        // Convert them all to the underlyings
        uint256 bdpiToMint;

        // Get total amount in bdpi
        (, uint256[] memory tokenAmountsInBasket) = BDPI.getAssetsAndBalances();

        // BDPI total supply
        uint256 basketTotalSupply = BDPI.totalSupply();

        // How much WETH to send
        uint256 wethToSend;
        bool success;

        for (uint256 i = 0; i < mmParams.constituents.length; i++) {
            // Convert them from WETH to their respective tokens
            wethToSend = _wethAmount.mul(mmParams.underlyingsWeights[i]).div(1e18);

            IWETH(WETH).approve(mmParams.routers[i], wethToSend);
            (success, ) = mmParams.routers[i].call(mmParams.routerCalldata[i]);
            require(success, "!swap");

            // Convert to from respective token to constituent
            _toConstituent(mmParams.underlyings[i], mmParams.constituents[i]);

            // Approve constituent and calculate mint amount
            bdpiToMint = _approveConstituentAndGetMintAmount(
                mmParams.constituents[i],
                basketTotalSupply,
                tokenAmountsInBasket[i],
                bdpiToMint
            );
        }

        // Mint tokens
        BDPI.mint(bdpiToMint);

        return bdpiToMint;
    }

    /// @notice Approves constituent to the basket address and gets the mint amount.
    ///         Mainly here to avoid stack too deep errors
    /// @param  constituent  Address of the constituent (e.g. cUNI, aYFI)
    /// @param  basketTotalSupply  Total supply of the basket token
    /// @param  tokenAmountInBasket  Amount of constituent currently in the basket
    /// @param  curMintAmount  Accumulator - whats the minimum mint amount right now
    function _approveConstituentAndGetMintAmount(
        address constituent,
        uint256 basketTotalSupply,
        uint256 tokenAmountInBasket,
        uint256 curMintAmount
    ) internal returns (uint256) {
        uint256 constituentBal = IERC20(constituent).balanceOf(address(this));

        IERC20(constituent).safeApprove(address(BDPI), 0);
        IERC20(constituent).safeApprove(address(BDPI), constituentBal);

        // Calculate how much BDPI we can mint at max
        // Formula: min(e for e in bdpiSupply * tokenWeHave[e] / tokenInBDPI[e])
        if (curMintAmount == 0) {
            return basketTotalSupply.mul(constituentBal).div(tokenAmountInBasket);
        }

        uint256 temp = basketTotalSupply.mul(constituentBal).div(tokenAmountInBasket);
        if (temp < curMintAmount) {
            return temp;
        }

        return curMintAmount;
    }
}

contract MarketMakerBurner is MarketMakerHelpers {
    using SafeERC20 for IERC20;
    using SafeMath for uint256;

    // **** Internals **** //

    // Burns BDPI to ETH
    function _burnBDIToWETH(uint256 _bdiAmount, bytes memory _mmData) internal returns (uint256) {
        MMParams memory mmParams = abi.decode(_mmData, (MMParams));

        (address[] memory underlyings, uint256[] memory underlyingAmounts) =
            _burnBDIAndGetUnderlyingAndAmounts(_bdiAmount);

        // Convert underlying to WETH
        bool success;
        for (uint256 i = 0; i < underlyings.length; i++) {
            // If we already have WETH then just skip it (e.g. yvBOOST or yveCRV)
            if (underlyings[i] != WETH && mmParams.routers[i] != address(0)) {
                IERC20(underlyings[i]).safeApprove(mmParams.routers[i], 0);
                IERC20(underlyings[i]).safeApprove(mmParams.routers[i], underlyingAmounts[i]);
                (success, ) = mmParams.routers[i].call(mmParams.routerCalldata[i]);
                require(success, "!swap");
            }
        }

        uint256 totalWETH = IERC20(WETH).balanceOf(address(this));
        return totalWETH;
    }

    function _burnBDIAndGetUnderlyingAndAmounts(uint256 _bdiAmount)
        internal
        returns (address[] memory, uint256[] memory)
    {
        (address[] memory assets, ) = IBasket(BDPI).getAssetsAndBalances();
        uint256[] memory deltas = new uint256[](assets.length);
        address[] memory underlyings = new address[](assets.length);
        uint256[] memory underlyingAmounts = new uint256[](assets.length);

        address underlying;
        uint256 underlyingAmount;

        for (uint256 i = 0; i < assets.length; i++) {
            deltas[i] = IERC20(assets[i]).balanceOf(address(this));
        }
        IBasket(BDPI).burn(_bdiAmount);
        for (uint256 i = 0; i < assets.length; i++) {
            deltas[i] = IERC20(assets[i]).balanceOf(address(this)).sub(deltas[i]);

            (underlying, underlyingAmount) = _toUnderlying(assets[i], deltas[i]);

            underlyings[i] = underlying;
            underlyingAmounts[i] = underlyingAmount;
        }

        return (underlyings, underlyingAmounts);
    }
}

contract BDIMarketMaker is MarketMakerBurner, MarketMakerMinter {
    receive() external payable {}
}

File 5 of 20: console.sol
// SPDX-License-Identifier: MIT
pragma solidity >= 0.4.22 <0.9.0;

library console {
	address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);

	function _sendLogPayload(bytes memory payload) private view {
		uint256 payloadLength = payload.length;
		address consoleAddress = CONSOLE_ADDRESS;
		assembly {
			let payloadStart := add(payload, 32)
			let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
		}
	}

	function log() internal view {
		_sendLogPayload(abi.encodeWithSignature("log()"));
	}

	function logInt(int p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(int)", p0));
	}

	function logUint(uint p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
	}

	function logString(string memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
	}

	function logBool(bool p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
	}

	function logAddress(address p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
	}

	function logBytes(bytes memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
	}

	function logBytes1(bytes1 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
	}

	function logBytes2(bytes2 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
	}

	function logBytes3(bytes3 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
	}

	function logBytes4(bytes4 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
	}

	function logBytes5(bytes5 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
	}

	function logBytes6(bytes6 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
	}

	function logBytes7(bytes7 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
	}

	function logBytes8(bytes8 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
	}

	function logBytes9(bytes9 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
	}

	function logBytes10(bytes10 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
	}

	function logBytes11(bytes11 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
	}

	function logBytes12(bytes12 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
	}

	function logBytes13(bytes13 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
	}

	function logBytes14(bytes14 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
	}

	function logBytes15(bytes15 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
	}

	function logBytes16(bytes16 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
	}

	function logBytes17(bytes17 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
	}

	function logBytes18(bytes18 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
	}

	function logBytes19(bytes19 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
	}

	function logBytes20(bytes20 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
	}

	function logBytes21(bytes21 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
	}

	function logBytes22(bytes22 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
	}

	function logBytes23(bytes23 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
	}

	function logBytes24(bytes24 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
	}

	function logBytes25(bytes25 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
	}

	function logBytes26(bytes26 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
	}

	function logBytes27(bytes27 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
	}

	function logBytes28(bytes28 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
	}

	function logBytes29(bytes29 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
	}

	function logBytes30(bytes30 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
	}

	function logBytes31(bytes31 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
	}

	function logBytes32(bytes32 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
	}

	function log(uint p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
	}

	function log(string memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
	}

	function log(bool p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
	}

	function log(address p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
	}

	function log(uint p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1));
	}

	function log(uint p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1));
	}

	function log(uint p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1));
	}

	function log(uint p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1));
	}

	function log(string memory p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1));
	}

	function log(string memory p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
	}

	function log(string memory p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
	}

	function log(string memory p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
	}

	function log(bool p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1));
	}

	function log(bool p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
	}

	function log(bool p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
	}

	function log(bool p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
	}

	function log(address p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1));
	}

	function log(address p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
	}

	function log(address p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
	}

	function log(address p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
	}

	function log(uint p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2));
	}

	function log(uint p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2));
	}

	function log(uint p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2));
	}

	function log(uint p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2));
	}

	function log(uint p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2));
	}

	function log(uint p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2));
	}

	function log(uint p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2));
	}

	function log(uint p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2));
	}

	function log(uint p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2));
	}

	function log(uint p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2));
	}

	function log(uint p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2));
	}

	function log(uint p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
	}

	function log(string memory p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2));
	}

	function log(string memory p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
	}

	function log(string memory p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
	}

	function log(string memory p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
	}

	function log(bool p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2));
	}

	function log(bool p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2));
	}

	function log(bool p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2));
	}

	function log(bool p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
	}

	function log(bool p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2));
	}

	function log(bool p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
	}

	function log(bool p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
	}

	function log(bool p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
	}

	function log(bool p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2));
	}

	function log(bool p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
	}

	function log(bool p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
	}

	function log(bool p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
	}

	function log(address p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2));
	}

	function log(address p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2));
	}

	function log(address p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2));
	}

	function log(address p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2));
	}

	function log(address p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2));
	}

	function log(address p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
	}

	function log(address p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
	}

	function log(address p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
	}

	function log(address p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2));
	}

	function log(address p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
	}

	function log(address p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
	}

	function log(address p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
	}

	function log(address p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2));
	}

	function log(address p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
	}

	function log(address p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
	}

	function log(address p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
	}

	function log(uint p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
	}

}

File 6 of 20: 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 7 of 20: EnumerableSet.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;

        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping (bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) { // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            bytes32 lastvalue = set._values[lastIndex];

            // Move the last value to the index where the value to delete is
            set._values[toDeleteIndex] = lastvalue;
            // Update the index for the moved value
            set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        require(set._values.length > index, "EnumerableSet: index out of bounds");
        return set._values[index];
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }


    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }
}

File 8 of 20: IATokenV1.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

interface IATokenV1 {
    function UINT_MAX_VALUE() external view returns (uint256);

    function allowInterestRedirectionTo(address _to) external;

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

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

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

    function burnOnLiquidation(address _account, uint256 _value) external;

    function decimals() external view returns (uint8);

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

    function getInterestRedirectionAddress(address _user) external view returns (address);

    function getRedirectedBalance(address _user) external view returns (uint256);

    function getUserIndex(address _user) external view returns (uint256);

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

    function isTransferAllowed(address _user, uint256 _amount) external view returns (bool);

    function mintOnDeposit(address _account, uint256 _amount) external;

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

    function principalBalanceOf(address _user) external view returns (uint256);

    function redeem(uint256 _amount) external;

    function redirectInterestStream(address _to) external;

    function redirectInterestStreamOf(address _from, address _to) external;

    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 underlyingAssetAddress() external view returns (address);
}

File 9 of 20: IBasket.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

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

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

    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 execute(address _module, bytes memory _data) external payable returns (bytes memory response);

    function grantRole(bytes32, address) external;

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

File 10 of 20: IComptroller.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

interface IComptroller {
    function _addCompMarkets(address[] memory cTokens) external;

    function _become(address unitroller) external;

    function _borrowGuardianPaused() external view returns (bool);

    function _dropCompMarket(address cToken) external;

    function _grantComp(address recipient, uint256 amount) external;

    function _mintGuardianPaused() external view returns (bool);

    function _setBorrowCapGuardian(address newBorrowCapGuardian) external;

    function _setBorrowPaused(address cToken, bool state) external returns (bool);

    function _setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256);

    function _setCollateralFactor(address cToken, uint256 newCollateralFactorMantissa) external returns (uint256);

    function _setCompRate(uint256 compRate_) external;

    function _setContributorCompSpeed(address contributor, uint256 compSpeed) external;

    function _setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external returns (uint256);

    function _setMarketBorrowCaps(address[] memory cTokens, uint256[] memory newBorrowCaps) external;

    function _setMintPaused(address cToken, bool state) external returns (bool);

    function _setPauseGuardian(address newPauseGuardian) external returns (uint256);

    function _setPriceOracle(address newOracle) external returns (uint256);

    function _setSeizePaused(bool state) external returns (bool);

    function _setTransferPaused(bool state) external returns (bool);

    function _supportMarket(address cToken) external returns (uint256);

    function accountAssets(address, uint256) external view returns (address);

    function admin() external view returns (address);

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

    function borrowAllowed(
        address cToken,
        address borrower,
        uint256 borrowAmount
    ) external returns (uint256);

    function borrowCapGuardian() external view returns (address);

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

    function borrowGuardianPaused(address) external view returns (bool);

    function borrowVerify(
        address cToken,
        address borrower,
        uint256 borrowAmount
    ) external;

    function checkMembership(address account, address cToken) external view returns (bool);

    function claimComp(address holder, address[] memory cTokens) external;

    function claimComp(
        address[] memory holders,
        address[] memory cTokens,
        bool borrowers,
        bool suppliers
    ) external;

    function claimComp(address holder) external;

    function closeFactorMantissa() external view returns (uint256);

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

    function compBorrowState(address) external view returns (uint224 index, uint32);

    function compBorrowerIndex(address, address) external view returns (uint256);

    function compClaimThreshold() external view returns (uint256);

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

    function compInitialIndex() external view returns (uint224);

    function compRate() external view returns (uint256);

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

    function compSupplierIndex(address, address) external view returns (uint256);

    function compSupplyState(address) external view returns (uint224 index, uint32);

    function comptrollerImplementation() external view returns (address);

    function enterMarkets(address[] memory cTokens) external returns (uint256[] memory);

    function exitMarket(address cTokenAddress) external returns (uint256);

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

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

    function getAssetsIn(address account) external view returns (address[] memory);

    function getBlockNumber() external view returns (uint256);

    function getCompAddress() external view returns (address);

    function getHypotheticalAccountLiquidity(
        address account,
        address cTokenModify,
        uint256 redeemTokens,
        uint256 borrowAmount
    )
        external
        view
        returns (
            uint256,
            uint256,
            uint256
        );

    function isComptroller() external view returns (bool);

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

    function liquidateBorrowAllowed(
        address cTokenBorrowed,
        address cTokenCollateral,
        address liquidator,
        address borrower,
        uint256 repayAmount
    ) external returns (uint256);

    function liquidateBorrowVerify(
        address cTokenBorrowed,
        address cTokenCollateral,
        address liquidator,
        address borrower,
        uint256 actualRepayAmount,
        uint256 seizeTokens
    ) external;

    function liquidateCalculateSeizeTokens(
        address cTokenBorrowed,
        address cTokenCollateral,
        uint256 actualRepayAmount
    ) external view returns (uint256, uint256);

    function liquidationIncentiveMantissa() external view returns (uint256);

    function markets(address)
        external
        view
        returns (
            bool isListed,
            uint256 collateralFactorMantissa,
            bool isComped
        );

    function maxAssets() external view returns (uint256);

    function mintAllowed(
        address cToken,
        address minter,
        uint256 mintAmount
    ) external returns (uint256);

    function mintGuardianPaused(address) external view returns (bool);

    function mintVerify(
        address cToken,
        address minter,
        uint256 actualMintAmount,
        uint256 mintTokens
    ) external;

    function oracle() external view returns (address);

    function pauseGuardian() external view returns (address);

    function pendingAdmin() external view returns (address);

    function pendingComptrollerImplementation() external view returns (address);

    function redeemAllowed(
        address cToken,
        address redeemer,
        uint256 redeemTokens
    ) external returns (uint256);

    function redeemVerify(
        address cToken,
        address redeemer,
        uint256 redeemAmount,
        uint256 redeemTokens
    ) external;

    function refreshCompSpeeds() external;

    function repayBorrowAllowed(
        address cToken,
        address payer,
        address borrower,
        uint256 repayAmount
    ) external returns (uint256);

    function repayBorrowVerify(
        address cToken,
        address payer,
        address borrower,
        uint256 actualRepayAmount,
        uint256 borrowerIndex
    ) external;

    function seizeAllowed(
        address cTokenCollateral,
        address cTokenBorrowed,
        address liquidator,
        address borrower,
        uint256 seizeTokens
    ) external returns (uint256);

    function seizeGuardianPaused() external view returns (bool);

    function seizeVerify(
        address cTokenCollateral,
        address cTokenBorrowed,
        address liquidator,
        address borrower,
        uint256 seizeTokens
    ) external;

    function transferAllowed(
        address cToken,
        address src,
        address dst,
        uint256 transferTokens
    ) external returns (uint256);

    function transferGuardianPaused() external view returns (bool);

    function transferVerify(
        address cToken,
        address src,
        address dst,
        uint256 transferTokens
    ) external;

    function updateContributorRewards(address contributor) external;
}

File 11 of 20: 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 12 of 20: ICurve.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

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

interface IveCurveVault {
    function CRV() external view returns (address);

    function DELEGATION_TYPEHASH() external view returns (bytes32);

    function DOMAINSEPARATOR() external view returns (bytes32);

    function DOMAIN_TYPEHASH() external view returns (bytes32);

    function LOCK() external view returns (address);

    function PERMIT_TYPEHASH() external view returns (bytes32);

    function acceptGovernance() external;

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

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

    function bal() external view returns (uint256);

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

    function checkpoints(address, uint32) external view returns (uint32 fromBlock, uint256 votes);

    function claim() external;

    function claimFor(address recipient) external;

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

    function decimals() external view returns (uint8);

    function delegate(address delegatee) external;

    function delegateBySig(
        address delegatee,
        uint256 nonce,
        uint256 expiry,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    function delegates(address) external view returns (address);

    function deposit(uint256 _amount) external;

    function depositAll() external;

    function feeDistribution() external view returns (address);

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

    function getPriorVotes(address account, uint256 blockNumber) external view returns (uint256);

    function governance() external view returns (address);

    function index() external view returns (uint256);

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

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

    function numCheckpoints(address) external view returns (uint32);

    function pendingGovernance() external view returns (address);

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

    function proxy() external view returns (address);

    function rewards() external view returns (address);

    function setFeeDistribution(address _feeDistribution) external;

    function setGovernance(address _governance) external;

    function setProxy(address _proxy) external;

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

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

    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 update() external;

    function updateFor(address recipient) external;
}

File 13 of 20: 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 14 of 20: ILendingPoolV1.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

interface ILendingPoolV1 {
    function LENDINGPOOL_REVISION() external view returns (uint256);

    function UINT_MAX_VALUE() external view returns (uint256);

    function addressesProvider() external view returns (address);

    function borrow(
        address _reserve,
        uint256 _amount,
        uint256 _interestRateMode,
        uint16 _referralCode
    ) external;

    function core() external view returns (address);

    function dataProvider() external view returns (address);

    function deposit(
        address _reserve,
        uint256 _amount,
        uint16 _referralCode
    ) external payable;

    function flashLoan(
        address _receiver,
        address _reserve,
        uint256 _amount,
        bytes memory _params
    ) external;

    function getReserveConfigurationData(address _reserve)
        external
        view
        returns (
            uint256 ltv,
            uint256 liquidationThreshold,
            uint256 liquidationBonus,
            address interestRateStrategyAddress,
            bool usageAsCollateralEnabled,
            bool borrowingEnabled,
            bool stableBorrowRateEnabled,
            bool isActive
        );

    function getReserveData(address _reserve)
        external
        view
        returns (
            uint256 totalLiquidity,
            uint256 availableLiquidity,
            uint256 totalBorrowsStable,
            uint256 totalBorrowsVariable,
            uint256 liquidityRate,
            uint256 variableBorrowRate,
            uint256 stableBorrowRate,
            uint256 averageStableBorrowRate,
            uint256 utilizationRate,
            uint256 liquidityIndex,
            uint256 variableBorrowIndex,
            address aTokenAddress,
            uint40 lastUpdateTimestamp
        );

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

    function getUserAccountData(address _user)
        external
        view
        returns (
            uint256 totalLiquidityETH,
            uint256 totalCollateralETH,
            uint256 totalBorrowsETH,
            uint256 totalFeesETH,
            uint256 availableBorrowsETH,
            uint256 currentLiquidationThreshold,
            uint256 ltv,
            uint256 healthFactor
        );

    function getUserReserveData(address _reserve, address _user)
        external
        view
        returns (
            uint256 currentATokenBalance,
            uint256 currentBorrowBalance,
            uint256 principalBorrowBalance,
            uint256 borrowRateMode,
            uint256 borrowRate,
            uint256 liquidityRate,
            uint256 originationFee,
            uint256 variableBorrowIndex,
            uint256 lastUpdateTimestamp,
            bool usageAsCollateralEnabled
        );

    function initialize(address _addressesProvider) external;

    function liquidationCall(
        address _collateral,
        address _reserve,
        address _user,
        uint256 _purchaseAmount,
        bool _receiveAToken
    ) external payable;

    function parametersProvider() external view returns (address);

    function rebalanceStableBorrowRate(address _reserve, address _user) external;

    function redeemUnderlying(
        address _reserve,
        address _user,
        uint256 _amount,
        uint256 _aTokenBalanceAfterRedeem
    ) external;

    function repay(
        address _reserve,
        uint256 _amount,
        address _onBehalfOf
    ) external payable;

    function setUserUseReserveAsCollateral(address _reserve, bool _useAsCollateral) external;

    function swapBorrowRateMode(address _reserve) external;
}

File 15 of 20: ISushiBar.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.3;

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

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

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

    function decimals() external view returns (uint8);

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

    function enter(uint256 _amount) external;

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

    function leave(uint256 _share) external;

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

    function sushi() external view returns (address);

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

File 16 of 20: IUniswapV2.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.0;

interface IUniswapV2Factory {
    event PairCreated(address indexed token0, address indexed token1, address pair, uint256);

    function feeTo() external view returns (address);

    function feeToSetter() external view returns (address);

    function migrator() external view returns (address);

    function getPair(address tokenA, address tokenB) external view returns (address pair);

    function allPairs(uint256) external view returns (address pair);

    function allPairsLength() external view returns (uint256);

    function createPair(address tokenA, address tokenB) external returns (address pair);

    function setFeeTo(address) external;

    function setFeeToSetter(address) external;

    function setMigrator(address) external;
}

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

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

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

    function decimals() external pure returns (uint8);

    function totalSupply() external view returns (uint256);

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

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

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

    function transfer(address to, uint256 value) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);

    function PERMIT_TYPEHASH() external pure returns (bytes32);

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

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

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

    function MINIMUM_LIQUIDITY() external pure returns (uint256);

    function factory() external view returns (address);

    function token0() external view returns (address);

    function token1() external view returns (address);

    function getReserves()
        external
        view
        returns (
            uint112 reserve0,
            uint112 reserve1,
            uint32 blockTimestampLast
        );

    function price0CumulativeLast() external view returns (uint256);

    function price1CumulativeLast() external view returns (uint256);

    function kLast() external view returns (uint256);

    function mint(address to) external returns (uint256 liquidity);

    function burn(address to) external returns (uint256 amount0, uint256 amount1);

    function swap(
        uint256 amount0Out,
        uint256 amount1Out,
        address to,
        bytes calldata data
    ) external;

    function skim(address to) external;

    function sync() external;

    function initialize(address, address) external;
}

interface IUniswapV2Router01 {
    function factory() external pure returns (address);

    function WETH() external pure returns (address);

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint256 amountADesired,
        uint256 amountBDesired,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline
    )
        external
        returns (
            uint256 amountA,
            uint256 amountB,
            uint256 liquidity
        );

    function addLiquidityETH(
        address token,
        uint256 amountTokenDesired,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    )
        external
        payable
        returns (
            uint256 amountToken,
            uint256 amountETH,
            uint256 liquidity
        );

    function removeLiquidity(
        address tokenA,
        address tokenB,
        uint256 liquidity,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountA, uint256 amountB);

    function removeLiquidityETH(
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountToken, uint256 amountETH);

    function removeLiquidityWithPermit(
        address tokenA,
        address tokenB,
        uint256 liquidity,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256 amountA, uint256 amountB);

    function removeLiquidityETHWithPermit(
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256 amountToken, uint256 amountETH);

    function swapExactTokensForTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function swapTokensForExactTokens(
        uint256 amountOut,
        uint256 amountInMax,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function swapExactETHForTokens(
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external payable returns (uint256[] memory amounts);

    function swapTokensForExactETH(
        uint256 amountOut,
        uint256 amountInMax,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function swapExactTokensForETH(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function swapETHForExactTokens(
        uint256 amountOut,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external payable returns (uint256[] memory amounts);

    function quote(
        uint256 amountA,
        uint256 reserveA,
        uint256 reserveB
    ) external pure returns (uint256 amountB);

    function getAmountOut(
        uint256 amountIn,
        uint256 reserveIn,
        uint256 reserveOut
    ) external pure returns (uint256 amountOut);

    function getAmountIn(
        uint256 amountOut,
        uint256 reserveIn,
        uint256 reserveOut
    ) external pure returns (uint256 amountIn);

    function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts);

    function getAmountsIn(uint256 amountOut, address[] calldata path) external view returns (uint256[] memory amounts);
}

interface IUniswapV2Router02 is IUniswapV2Router01 {
    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountETH);

    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256 amountETH);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external;

    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external payable;

    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external;
}

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

pragma solidity ^0.7.3;

interface IWETH {
    function name() external view returns (string memory);

    function approve(address guy, uint256 wad) external returns (bool);

    function totalSupply() external view returns (uint256);

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

    function withdraw(uint256 wad) external;

    function decimals() external view returns (uint8);

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

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

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

    function deposit() external payable;

    function allowance(address, address) external view returns (uint256);
}

File 18 of 20: 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 19 of 20: 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 20 of 20: 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":[{"internalType":"address","name":"_governance","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"_depositTime","type":"uint256"}],"name":"_canBurn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_atoken","type":"address"}],"name":"_isATokenV1","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_ctoken","type":"address"}],"name":"_isCToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"}],"name":"_isYearnV2","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"burn","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"burnDelaySeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"routers","type":"address[]"},{"internalType":"bytes[]","name":"routerCalldata","type":"bytes[]"},{"internalType":"address[]","name":"constituents","type":"address[]"},{"internalType":"address[]","name":"underlyings","type":"address[]"},{"internalType":"uint256[]","name":"underlyingsWeights","type":"uint256[]"},{"internalType":"uint256","name":"_minETHAmount","type":"uint256"}],"name":"burnToETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"deposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_markets","type":"address[]"}],"name":"enterMarkets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isBlacklisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxBurnDelaySeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"rescueERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"}],"name":"rescueERC20s","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"bool","name":"_b","type":"bool"}],"name":"setBlacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_seconds","type":"uint256"}],"name":"setBurnDelaySeconds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_governance","type":"address"}],"name":"setGov","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_seconds","type":"uint256"}],"name":"setMaxBurnDelaySeconds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"timestampWhenDeposited","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60806040526104b06000556109606001553480156200001d57600080fd5b5060405162003f1138038062003f118339810160408190526200004091620003ca565b600280546001600160a01b0319166001600160a01b0383161790556200009e73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273d9e1ce17f2641f24ae83637ab66a2cca9c378b9f600019620000e8602090811b6200109a17901c565b620000e173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2737a250d5630b4cf539739df2c5dacb4c659f2488d600019620000e8602090811b6200109a17901c565b506200060b565b801580620001775750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e906200012190309086906004016200044c565b60206040518083038186803b1580156200013a57600080fd5b505afa1580156200014f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000175919062000415565b155b6200019f5760405162461bcd60e51b815260040162000196906200057b565b60405180910390fd5b620001fa8363095ea7b360e01b8484604051602401620001c192919062000466565b60408051808303601f190181529190526020810180516001600160e01b0319939093166001600160e01b0393841617905290620001ff16565b505050565b60606200025b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166200029b60201b62001199179092919060201c565b805190915015620001fa57808060200190518101906200027c9190620003f3565b620001fa5760405162461bcd60e51b8152600401620001969062000531565b6060620002ac8484600085620002b6565b90505b9392505050565b606082471015620002db5760405162461bcd60e51b81526004016200019690620004b4565b620002e68562000386565b620003055760405162461bcd60e51b81526004016200019690620004fa565b60006060866001600160a01b031685876040516200032491906200042e565b60006040518083038185875af1925050503d806000811462000363576040519150601f19603f3d011682016040523d82523d6000602084013e62000368565b606091505b5090925090506200037b8282866200038c565b979650505050505050565b3b151590565b606083156200039d575081620002af565b825115620003ae5782518084602001fd5b8160405162461bcd60e51b81526004016200019691906200047f565b600060208284031215620003dc578081fd5b81516001600160a01b0381168114620002af578182fd5b60006020828403121562000405578081fd5b81518015158114620002af578182fd5b60006020828403121562000427578081fd5b5051919050565b6000825162000442818460208701620005d8565b9190910192915050565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b6000602082528251806020840152620004a0816040850160208701620005d8565b601f01601f19169190910160400192915050565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606082015260800190565b60005b83811015620005f5578181015183820152602001620005db565b8381111562000605576000848401525b50505050565b6138f6806200061b6000396000f3fe60806040526004361061012e5760003560e01c8063a0509241116100ab578063c29982381161006f578063c29982381461032d578063ccec37161461034d578063cfad57a21461036d578063fb6d25f41461038d578063fc7e286d146103ad578063fe575a87146103cd57610135565b8063a05092411461028d578063a300c34e146102ad578063afe9dc7e146102cd578063b6b55f25146102ed578063bf58931e1461030d57610135565b806337b2def0116100f257806337b2def0146101ff5780633b7991721461021457806344df8e70146102345780635aa6e6751461025657806361311eef1461027857610135565b80630833f5841461013a578063153b0d1e1461015c57806315756f681461017c5780632e1a7d4d146101b25780633633643b146101d257610135565b3661013557005b600080fd5b34801561014657600080fd5b5061015a610155366004612f77565b6103ed565b005b34801561016857600080fd5b5061015a610177366004612f3f565b610454565b34801561018857600080fd5b5061019c610197366004613223565b6104a9565b6040516101a991906133a1565b60405180910390f35b3480156101be57600080fd5b5061015a6101cd366004613223565b6104c8565b3480156101de57600080fd5b506101f26101ed366004612f07565b610518565b6040516101a991906137af565b34801561020b57600080fd5b506101f261052a565b34801561022057600080fd5b5061019c61022f366004612f07565b610530565b34801561024057600080fd5b5061024961057b565b6040516101a9919061338e565b34801561026257600080fd5b5061026b6109ba565b6040516101a99190613310565b34801561028457600080fd5b506101f26109c9565b34801561029957600080fd5b5061015a6102a8366004613223565b6109cf565b3480156102b957600080fd5b506101f26102c8366004612fb2565b6109fe565b3480156102d957600080fd5b5061019c6102e8366004612f07565b610cb4565b3480156102f957600080fd5b5061015a610308366004613223565b610d74565b34801561031957600080fd5b5061019c610328366004612f07565b610dcf565b34801561033957600080fd5b5061015a610348366004612f77565b610e68565b34801561035957600080fd5b5061015a610368366004612f07565b610ef5565b34801561037957600080fd5b5061015a610388366004612f07565b610ff8565b34801561039957600080fd5b5061015a6103a8366004613223565b611044565b3480156103b957600080fd5b506101f26103c8366004612f07565b611073565b3480156103d957600080fd5b5061019c6103e8366004612f07565b611085565b6002546001600160a01b031633146104205760405162461bcd60e51b8152600401610417906133bf565b60405180910390fd5b60005b81518110156104505761044882828151811061043b57fe5b6020026020010151610ef5565b600101610423565b5050565b6002546001600160a01b0316331461047e5760405162461bcd60e51b8152600401610417906133bf565b6001600160a01b03919091166000908152600560205260409020805460ff1916911515919091179055565b60008054820142101580156104c2575060015482014211155b92915050565b336000908152600360205260409020546104e290826111b2565b3360008181526003602052604090209190915561051590730309c98b1bffa350bcb3f9fb9780970ca32a506090836111da565b50565b60046020526000908152604090205481565b60015481565b60006001600160a01b0382167370e36f6bf80a52b3b46b3af8e106cc0ed743e8e414806104c25750506001600160a01b03167335a18000230da775cac24873d00ff85bccded5501490565b606033321461059c5760405162461bcd60e51b81526004016104179061359e565b3360009081526005602052604090205460ff16156105cc5760405162461bcd60e51b8152600401610417906135f3565b33600090815260036020526040902054806105f95760405162461bcd60e51b815260040161041790613618565b33600090815260046020526040902054610612906104a9565b61062e5760405162461bcd60e51b815260040161041790613403565b33600090815260036020526040808220829055805163db57925760e01b81529051606092730309c98b1bffa350bcb3f9fb9780970ca32a50609263db5792579260048083019392829003018186803b15801561068957600080fd5b505afa15801561069d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106c59190810190613086565b5090506060815167ffffffffffffffff811180156106e257600080fd5b5060405190808252806020026020018201604052801561070c578160200160208202803683370190505b50905060005b82518110156107c95782818151811061072757fe5b60200260200101516001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161075a9190613310565b60206040518083038186803b15801561077257600080fd5b505afa158015610786573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107aa919061323b565b8282815181106107b657fe5b6020908102919091010152600101610712565b50604051630852cd8d60e31b8152730309c98b1bffa350bcb3f9fb9780970ca32a5060906342966c68906108019086906004016137af565b600060405180830381600087803b15801561081b57600080fd5b505af115801561082f573d6000803e3d6000fd5b5050505060005b82518110156109b2576108eb82828151811061084e57fe5b602002602001015184838151811061086257fe5b60200260200101516001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016108959190613310565b60206040518083038186803b1580156108ad57600080fd5b505afa1580156108c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e5919061323b565b906111b2565b8282815181106108f757fe5b60200260200101818152505082818151811061090f57fe5b60200260200101516001600160a01b031663a9059cbb3384848151811061093257fe5b60200260200101516040518363ffffffff1660e01b8152600401610957929190613324565b602060405180830381600087803b15801561097157600080fd5b505af1158015610985573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a99190613110565b50600101610836565b509250505090565b6002546001600160a01b031681565b60005481565b6002546001600160a01b031633146109f95760405162461bcd60e51b8152600401610417906133bf565b600155565b6000333214610a1f5760405162461bcd60e51b81526004016104179061359e565b3360009081526005602052604090205460ff1615610a4f5760405162461bcd60e51b8152600401610417906135f3565b3360009081526003602052604090205480610a7c5760405162461bcd60e51b815260040161041790613618565b33600090815260046020526040902054610a95906104a9565b610ab15760405162461bcd60e51b815260040161041790613403565b33600090815260036020908152604080832092909255815160a0810183528a81528082018a90528083018990526060818101899052608082018890529251610af992016136d9565b6040516020818303038152906040529050610b1482826111f9565b506040516370a0823160e01b815260009073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2906370a0823190610b4f903090600401613310565b60206040518083038186803b158015610b6757600080fd5b505afa158015610b7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b9f919061323b565b905084811015610bc15760405162461bcd60e51b815260040161041790613575565b604051632e1a7d4d60e01b815273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d90610bf89084906004016137af565b600060405180830381600087803b158015610c1257600080fd5b505af1158015610c26573d6000803e3d6000fd5b505050506000336001600160a01b031682604051610c439061330d565b60006040518083038185875af1925050503d8060008114610c80576040519150601f19603f3d011682016040523d82523d6000602084013e610c85565b606091505b5050905080610ca65760405162461bcd60e51b81526004016104179061345e565b509998505050505050505050565b60006001600160a01b0382167312e51e77daaa58aa0e9247db7510ea4b46f9bead1480610cfd57506001600160a01b03821673328c4c80bc7aca0834db37e6600a6c49e12da4de145b80610d2457506001600160a01b038216737deb5e830be29f91e298ba5ff1356bb7f8146998145b80610d4b57506001600160a01b0382167369948cc03f478b95283f7dbf1ce764d0fc7ec54c145b806104c25750506001600160a01b0316739d91be44c06d373a8a226e1f3b146956083803eb1490565b610d94730309c98b1bffa350bcb3f9fb9780970ca32a5060333084611472565b33600090815260036020526040902054610dae9082611499565b33600090815260036020908152604080832093909355600490522042905550565b60006001600160a01b03821673f2db9a7c0acd427a680d640f02d90f6186e717251480610e1857506001600160a01b03821673fbeb78a723b8087fd2ea7ef1afec93d35e8bed42145b80610e3f57506001600160a01b03821673e14d13d8b3b85af791b2aadd661cdbd5e6097db1145b806104c25750506001600160a01b031673f29ae508698bdef169b89834f76704c3b205aedf1490565b604051631853304760e31b8152733d9819210a31b4961b30ef54be2aed79b9c9cd3b9063c299823890610e9f90849060040161337b565b600060405180830381600087803b158015610eb957600080fd5b505af1158015610ecd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261045091908101906130dd565b6002546001600160a01b03163314610f1f5760405162461bcd60e51b8152600401610417906133bf565b6001600160a01b038116730309c98b1bffa350bcb3f9fb9780970ca32a50601415610f5c5760405162461bcd60e51b8152600401610417906133e4565b6040516370a0823160e01b81526000906001600160a01b038316906370a0823190610f8b903090600401613310565b60206040518083038186803b158015610fa357600080fd5b505afa158015610fb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fdb919061323b565b600254909150610450906001600160a01b038481169116836111da565b6002546001600160a01b031633146110225760405162461bcd60e51b8152600401610417906133bf565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6002546001600160a01b0316331461106e5760405162461bcd60e51b8152600401610417906133bf565b600055565b60036020526000908152604090205481565b60056020526000908152604090205460ff1681565b8015806111225750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e906110d0903090869060040161333d565b60206040518083038186803b1580156110e857600080fd5b505afa1580156110fc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611120919061323b565b155b61113e5760405162461bcd60e51b815260040161041790613683565b6111948363095ea7b360e01b848460405160240161115d929190613324565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526114be565b505050565b60606111a8848460008561154d565b90505b9392505050565b6000828211156111d45760405162461bcd60e51b815260040161041790613485565b50900390565b6111948363a9059cbb60e01b848460405160240161115d929190613324565b6000611203612c13565b82806020019051810190611217919061312c565b90506060806112258661160e565b90925090506000805b83518110156113db5773c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031684828151811061126157fe5b60200260200101516001600160a01b0316141580156112a1575084518051600091908390811061128d57fe5b60200260200101516001600160a01b031614155b156113d3576112ef856000015182815181106112b957fe5b602002602001015160008684815181106112cf57fe5b60200260200101516001600160a01b031661109a9092919063ffffffff16565b61132a8560000151828151811061130257fe5b602002602001015184838151811061131657fe5b60200260200101518684815181106112cf57fe5b845180518290811061133857fe5b60200260200101516001600160a01b03168560200151828151811061135957fe5b602002602001015160405161136e91906132f1565b6000604051808303816000865af19150503d80600081146113ab576040519150601f19603f3d011682016040523d82523d6000602084013e6113b0565b606091505b505080925050816113d35760405162461bcd60e51b815260040161041790613502565b60010161122e565b506040516370a0823160e01b815260009073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2906370a0823190611416903090600401613310565b60206040518083038186803b15801561142e57600080fd5b505afa158015611442573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611466919061323b565b98975050505050505050565b611493846323b872dd60e01b85858560405160240161115d93929190613357565b50505050565b6000828201838110156111ab5760405162461bcd60e51b815260040161041790613427565b6060611513826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166111999092919063ffffffff16565b80519091501561119457808060200190518101906115319190613110565b6111945760405162461bcd60e51b815260040161041790613639565b60608247101561156f5760405162461bcd60e51b8152600401610417906134bc565b61157885611977565b6115945760405162461bcd60e51b8152600401610417906135bc565b60006060866001600160a01b031685876040516115b191906132f1565b60006040518083038185875af1925050503d80600081146115ee576040519150601f19603f3d011682016040523d82523d6000602084013e6115f3565b606091505b509150915061160382828661197d565b979650505050505050565b6060806060730309c98b1bffa350bcb3f9fb9780970ca32a50606001600160a01b031663db5792576040518163ffffffff1660e01b815260040160006040518083038186803b15801561166057600080fd5b505afa158015611674573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261169c9190810190613086565b5090506060815167ffffffffffffffff811180156116b957600080fd5b506040519080825280602002602001820160405280156116e3578160200160208202803683370190505b5090506060825167ffffffffffffffff8111801561170057600080fd5b5060405190808252806020026020018201604052801561172a578160200160208202803683370190505b5090506060835167ffffffffffffffff8111801561174757600080fd5b50604051908082528060200260200182016040528015611771578160200160208202803683370190505b50905060008060005b86518110156118315786818151811061178f57fe5b60200260200101516001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016117c29190613310565b60206040518083038186803b1580156117da57600080fd5b505afa1580156117ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611812919061323b565b86828151811061181e57fe5b602090810291909101015260010161177a565b50604051630852cd8d60e31b8152730309c98b1bffa350bcb3f9fb9780970ca32a5060906342966c6890611869908c906004016137af565b600060405180830381600087803b15801561188357600080fd5b505af1158015611897573d6000803e3d6000fd5b5050505060005b8651811015611967576118ca8682815181106118b657fe5b602002602001015188838151811061086257fe5b8682815181106118d657fe5b6020026020010181815250506119128782815181106118f157fe5b602002602001015187838151811061190557fe5b60200260200101516119b6565b80935081945050508285828151811061192757fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508184828151811061195457fe5b602090810291909101015260010161189e565b5092965090945050505050915091565b3b151590565b6060831561198c5750816111ab565b82511561199c5782518084602001fd5b8160405162461bcd60e51b815260040161041791906133ac565b6000806119c284610530565b156119da576119d18484611ea7565b91509150611ea0565b6119e384610cb4565b156119f2576119d184846120d6565b6001600160a01b038416738798249c2e607446efb7ad49ec89dd1865ff42721415611a20576119d18361225b565b6001600160a01b03841673cee60cfa923170e4f8204ae08b4fa6a3f5656f3a1415611a4e576119d1836123b5565b6001600160a01b03841673fd4d8a17df4c27c1dd245d153ccf4499e806c87d1415611a94576000611a7e8461258b565b915050611a8a816123b5565b9250925050611ea0565b6001600160a01b03841673f2db9a7c0acd427a680d640f02d90f6186e717251415611ac4576000611a7e84612730565b6001600160a01b038416739d409a0a012cfba9b15f6d4b36ac57a46966ab9a1480611b0b57506001600160a01b03841673c5bddf9843308380375a611c18b50fb9341f502a145b15611dda576001600160a01b03841673c5bddf9843308380375a611c18b50fb9341f502a1415611b3d57611b3d612885565b6040805160028082526060808301845292602083019080368337019050509050739d409a0a012cfba9b15f6d4b36ac57a46966ab9a81600081518110611b7f57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281600181518110611bc157fe5b6001600160a01b03909216602092830291909101909101526040516370a0823160e01b8152600090739d409a0a012cfba9b15f6d4b36ac57a46966ab9a906370a0823190611c13903090600401613310565b60206040518083038186803b158015611c2b57600080fd5b505afa158015611c3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c63919061323b565b60405163095ea7b360e01b8152909150739d409a0a012cfba9b15f6d4b36ac57a46966ab9a9063095ea7b390611cb39073d9e1ce17f2641f24ae83637ab66a2cca9c378b9f908590600401613324565b602060405180830381600087803b158015611ccd57600080fd5b505af1158015611ce1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d059190613110565b506040516338ed173960e01b815260609073d9e1ce17f2641f24ae83637ab66a2cca9c378b9f906338ed173990611d4c90859060009088903090603c4201906004016137b8565b600060405180830381600087803b158015611d6657600080fd5b505af1158015611d7a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611da291908101906130dd565b905073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281600181518110611dc657fe5b602002602001015194509450505050611ea0565b6001600160a01b03841673f2db9a7c0acd427a680d640f02d90f6186e717251480611e2157506001600160a01b03841673fbeb78a723b8087fd2ea7ef1afec93d35e8bed42145b80611e4857506001600160a01b03841673e14d13d8b3b85af791b2aadd661cdbd5e6097db1145b80611e6f57506001600160a01b03841673f29ae508698bdef169b89834f76704c3b205aedf145b15611e9a57600080611e818686612a01565b91509150611e8f82826119b6565b935093505050611ea0565b50829050815b9250929050565b6000806001600160a01b0384167335a18000230da775cac24873d00ff85bccded5501480611ef157506001600160a01b0384167370e36f6bf80a52b3b46b3af8e106cc0ed743e8e4145b611f0d5760405162461bcd60e51b815260040161041790613549565b836001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015611f4657600080fd5b505afa158015611f5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f7e9190612f23565b91506000826001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611fae9190613310565b60206040518083038186803b158015611fc657600080fd5b505afa158015611fda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ffe919061323b565b60405163db006a7560e01b81529091506001600160a01b0386169063db006a759061202d9087906004016137af565b602060405180830381600087803b15801561204757600080fd5b505af115801561205b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061207f919061323b565b1561209c5760405162461bcd60e51b815260040161041790613521565b6120cc81846001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016108959190613310565b9150509250929050565b600080836001600160a01b03166389d1a0fc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561211257600080fd5b505afa158015612126573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061214a9190612f23565b91506000826001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161217a9190613310565b60206040518083038186803b15801561219257600080fd5b505afa1580156121a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ca919061323b565b60405163db006a7560e01b81529091506001600160a01b0386169063db006a75906121f99087906004016137af565b600060405180830381600087803b15801561221357600080fd5b505af1158015612227573d6000803e3d6000fd5b505050506120cc81846001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016108959190613310565b6040516370a0823160e01b815260009081908190736b3595068778dd592e39a122f4f5a5cf09c90fe2906370a0823190612299903090600401613310565b60206040518083038186803b1580156122b157600080fd5b505afa1580156122c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122e9919061323b565b6040516367dfd4c960e01b8152909150738798249c2e607446efb7ad49ec89dd1865ff4272906367dfd4c9906123239087906004016137af565b600060405180830381600087803b15801561233d57600080fd5b505af1158015612351573d6000803e3d6000fd5b50506040516370a0823160e01b81526000925061239591508390736b3595068778dd592e39a122f4f5a5cf09c90fe2906370a0823190610895903090600401613310565b736b3595068778dd592e39a122f4f5a5cf09c90fe2945092505050915091565b6040516370a0823160e01b81526000908190819073514910771af9ca656af840dff83e8264ecf986ca906370a08231906123f3903090600401613310565b60206040518083038186803b15801561240b57600080fd5b505afa15801561241f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612443919061323b565b604051630d2680e960e11b815290915073f178c0b5bb7e7abf4e12a4838c7b7c5ba2c623c090631a4d01d29061248290879060009081906004016137f4565b602060405180830381600087803b15801561249c57600080fd5b505af11580156124b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124d4919061323b565b506040516370a0823160e01b815260009073514910771af9ca656af840dff83e8264ecf986ca906370a082319061250f903090600401613310565b60206040518083038186803b15801561252757600080fd5b505afa15801561253b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061255f919061323b565b905073514910771af9ca656af840dff83e8264ecf986ca61258082846111b2565b935093505050915091565b6040516370a0823160e01b81526000908190819073cee60cfa923170e4f8204ae08b4fa6a3f5656f3a906370a08231906125c9903090600401613310565b60206040518083038186803b1580156125e157600080fd5b505afa1580156125f5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612619919061323b565b604051632e1a7d4d60e01b815290915073fd4d8a17df4c27c1dd245d153ccf4499e806c87d90632e1a7d4d906126539087906004016137af565b600060405180830381600087803b15801561266d57600080fd5b505af1158015612681573d6000803e3d6000fd5b50506040516370a0823160e01b81526000925073cee60cfa923170e4f8204ae08b4fa6a3f5656f3a91506370a08231906126bf903090600401613310565b60206040518083038186803b1580156126d757600080fd5b505afa1580156126eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061270f919061323b565b905073cee60cfa923170e4f8204ae08b4fa6a3f5656f3a61258082846111b2565b6040516370a0823160e01b81526000908190819073cee60cfa923170e4f8204ae08b4fa6a3f5656f3a906370a082319061276e903090600401613310565b60206040518083038186803b15801561278657600080fd5b505afa15801561279a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127be919061323b565b604051632e1a7d4d60e01b815290915073f2db9a7c0acd427a680d640f02d90f6186e7172590632e1a7d4d906127f89087906004016137af565b602060405180830381600087803b15801561281257600080fd5b505af1158015612826573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061284a919061323b565b506040516370a0823160e01b815260009073cee60cfa923170e4f8204ae08b4fa6a3f5656f3a906370a08231906126bf903090600401613310565b6040516370a0823160e01b815260009073c5bddf9843308380375a611c18b50fb9341f502a906370a08231906128bf903090600401613310565b60206040518083038186803b1580156128d757600080fd5b505afa1580156128eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061290f919061323b565b905061294573c5bddf9843308380375a611c18b50fb9341f502a739d409a0a012cfba9b15f6d4b36ac57a46966ab9a600061109a565b61297873c5bddf9843308380375a611c18b50fb9341f502a739d409a0a012cfba9b15f6d4b36ac57a46966ab9a8361109a565b60405163b6b55f2560e01b8152739d409a0a012cfba9b15f6d4b36ac57a46966ab9a9063b6b55f25906129af9084906004016137af565b602060405180830381600087803b1580156129c957600080fd5b505af11580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610450919061323b565b6000806000846001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b158015612a3f57600080fd5b505afa158015612a53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a779190612f23565b90506000816001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401612aa79190613310565b60206040518083038186803b158015612abf57600080fd5b505afa158015612ad3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612af7919061323b565b604051632e1a7d4d60e01b81529091506001600160a01b03871690632e1a7d4d90612b269088906004016137af565b602060405180830381600087803b158015612b4057600080fd5b505af1158015612b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b78919061323b565b506040516370a0823160e01b81526000906001600160a01b038416906370a0823190612ba8903090600401613310565b60206040518083038186803b158015612bc057600080fd5b505afa158015612bd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bf8919061323b565b905082612c0582846111b2565b945094505050509250929050565b6040518060a0016040528060608152602001606081526020016060815260200160608152602001606081525090565b600082601f830112612c52578081fd5b8135612c65612c6082613831565b61380d565b818152915060208083019084810181840286018201871015612c8657600080fd5b60005b84811015612cae578135612c9c8161389d565b84529282019290820190600101612c89565b505050505092915050565b600082601f830112612cc9578081fd5b8151612cd7612c6082613831565b818152915060208083019084810181840286018201871015612cf857600080fd5b60005b84811015612cae578151612d0e8161389d565b84529282019290820190600101612cfb565b600082601f830112612d30578081fd5b8135612d3e612c6082613831565b818152915060208083019084810160005b84811015612cae578135870188603f820112612d6a57600080fd5b83810135612d7a612c608261384f565b81815260408b81848601011115612d9057600080fd5b82818501888401375060009181018601919091528552509282019290820190600101612d4f565b600082601f830112612dc7578081fd5b8151612dd5612c6082613831565b818152915060208083019084810160005b84811015612cae578151870188603f820112612e0157600080fd5b83810151612e11612c608261384f565b81815260408b81848601011115612e2757600080fd5b612e3683888401838701613871565b50865250509282019290820190600101612de6565b600082601f830112612e5b578081fd5b8135612e69612c6082613831565b818152915060208083019084810181840286018201871015612e8a57600080fd5b60005b84811015612cae57813584529282019290820190600101612e8d565b600082601f830112612eb9578081fd5b8151612ec7612c6082613831565b818152915060208083019084810181840286018201871015612ee857600080fd5b60005b84811015612cae57815184529282019290820190600101612eeb565b600060208284031215612f18578081fd5b81356111ab8161389d565b600060208284031215612f34578081fd5b81516111ab8161389d565b60008060408385031215612f51578081fd5b8235612f5c8161389d565b91506020830135612f6c816138b2565b809150509250929050565b600060208284031215612f88578081fd5b813567ffffffffffffffff811115612f9e578182fd5b612faa84828501612c42565b949350505050565b60008060008060008060c08789031215612fca578182fd5b863567ffffffffffffffff80821115612fe1578384fd5b612fed8a838b01612c42565b97506020890135915080821115613002578384fd5b61300e8a838b01612d20565b96506040890135915080821115613023578384fd5b61302f8a838b01612c42565b95506060890135915080821115613044578384fd5b6130508a838b01612c42565b94506080890135915080821115613065578384fd5b5061307289828a01612e4b565b92505060a087013590509295509295509295565b60008060408385031215613098578182fd5b825167ffffffffffffffff808211156130af578384fd5b6130bb86838701612cb9565b935060208501519150808211156130d0578283fd5b506120cc85828601612ea9565b6000602082840312156130ee578081fd5b815167ffffffffffffffff811115613104578182fd5b612faa84828501612ea9565b600060208284031215613121578081fd5b81516111ab816138b2565b60006020828403121561313d578081fd5b815167ffffffffffffffff80821115613154578283fd5b9083019060a08286031215613167578283fd5b61317160a061380d565b82518281111561317f578485fd5b61318b87828601612cb9565b82525060208301518281111561319f578485fd5b6131ab87828601612db7565b6020830152506040830151828111156131c2578485fd5b6131ce87828601612cb9565b6040830152506060830151828111156131e5578485fd5b6131f187828601612cb9565b606083015250608083015182811115613208578485fd5b61321487828601612ea9565b60808301525095945050505050565b600060208284031215613234578081fd5b5035919050565b60006020828403121561324c578081fd5b5051919050565b6000815180845260208085019450808401835b8381101561328b5781516001600160a01b031687529582019590820190600101613266565b509495945050505050565b6000815180845260208085019450808401835b8381101561328b578151875295820195908201906001016132a9565b600081518084526132dd816020860160208601613871565b601f01601f19169290920160200192915050565b60008251613303818460208701613871565b9190910192915050565b90565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6000602082526111ab6020830184613253565b6000602082526111ab6020830184613296565b901515815260200190565b6000602082526111ab60208301846132c5565b6020808252600b908201526a21676f7665726e616e636560a81b604082015260600190565b602080825260059082015264216264706960d81b604082015260600190565b6020808252600a908201526902174696d657374616d760b41b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252600d908201526c10b2ba3416ba3930b739b332b960991b604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b602080825260059082015264021737761760dc1b604082015260600190565b6020808252600e908201526d2163746f6b656e2d72656465656d60901b604082015260600190565b60208082526012908201527110bb30b634b216b33937b696b1ba37b5b2b760711b604082015260600190565b6020808252600f908201526e085b5a5b8b595d1a0b585b5bdd5b9d608a1b604082015260600190565b60208082526004908201526321656f6160e01b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a189b1858dadb1a5cdd195960aa1b604082015260600190565b60208082526007908201526608585b5bdd5b9d60ca1b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606082015260800190565b60006020808352835160a0828501526136f560c0850182613253565b82860151601f19868303810160408801528151808452929350908401918385019080860285018601875b8281101561374b57848783030184526137398287516132c5565b9588019593880193915060010161371f565b5060408a01519650838982030160608a01526137678188613253565b965050505060608701519250808685030160808701526137878484613253565b935060808701519250808685030160a087015250506137a68282613296565b95945050505050565b90815260200190565b600086825285602083015260a060408301526137d760a0830186613253565b6001600160a01b0394909416606083015250608001529392505050565b928352600f9190910b6020830152604082015260600190565b60405181810167ffffffffffffffff8111828210171561382957fe5b604052919050565b600067ffffffffffffffff82111561384557fe5b5060209081020190565b600067ffffffffffffffff82111561386357fe5b50601f01601f191660200190565b60005b8381101561388c578181015183820152602001613874565b838111156114935750506000910152565b6001600160a01b038116811461051557600080fd5b801515811461051557600080fdfea26469706673582212202b1c2a16b490a272394d6728ea3eeba1c311f65b6bcfce87bc61bfce987b34b264736f6c63430007030033000000000000000000000000f337a885a7543cab542b2d3f5a8c1945036e0c42

Deployed Bytecode

0x60806040526004361061012e5760003560e01c8063a0509241116100ab578063c29982381161006f578063c29982381461032d578063ccec37161461034d578063cfad57a21461036d578063fb6d25f41461038d578063fc7e286d146103ad578063fe575a87146103cd57610135565b8063a05092411461028d578063a300c34e146102ad578063afe9dc7e146102cd578063b6b55f25146102ed578063bf58931e1461030d57610135565b806337b2def0116100f257806337b2def0146101ff5780633b7991721461021457806344df8e70146102345780635aa6e6751461025657806361311eef1461027857610135565b80630833f5841461013a578063153b0d1e1461015c57806315756f681461017c5780632e1a7d4d146101b25780633633643b146101d257610135565b3661013557005b600080fd5b34801561014657600080fd5b5061015a610155366004612f77565b6103ed565b005b34801561016857600080fd5b5061015a610177366004612f3f565b610454565b34801561018857600080fd5b5061019c610197366004613223565b6104a9565b6040516101a991906133a1565b60405180910390f35b3480156101be57600080fd5b5061015a6101cd366004613223565b6104c8565b3480156101de57600080fd5b506101f26101ed366004612f07565b610518565b6040516101a991906137af565b34801561020b57600080fd5b506101f261052a565b34801561022057600080fd5b5061019c61022f366004612f07565b610530565b34801561024057600080fd5b5061024961057b565b6040516101a9919061338e565b34801561026257600080fd5b5061026b6109ba565b6040516101a99190613310565b34801561028457600080fd5b506101f26109c9565b34801561029957600080fd5b5061015a6102a8366004613223565b6109cf565b3480156102b957600080fd5b506101f26102c8366004612fb2565b6109fe565b3480156102d957600080fd5b5061019c6102e8366004612f07565b610cb4565b3480156102f957600080fd5b5061015a610308366004613223565b610d74565b34801561031957600080fd5b5061019c610328366004612f07565b610dcf565b34801561033957600080fd5b5061015a610348366004612f77565b610e68565b34801561035957600080fd5b5061015a610368366004612f07565b610ef5565b34801561037957600080fd5b5061015a610388366004612f07565b610ff8565b34801561039957600080fd5b5061015a6103a8366004613223565b611044565b3480156103b957600080fd5b506101f26103c8366004612f07565b611073565b3480156103d957600080fd5b5061019c6103e8366004612f07565b611085565b6002546001600160a01b031633146104205760405162461bcd60e51b8152600401610417906133bf565b60405180910390fd5b60005b81518110156104505761044882828151811061043b57fe5b6020026020010151610ef5565b600101610423565b5050565b6002546001600160a01b0316331461047e5760405162461bcd60e51b8152600401610417906133bf565b6001600160a01b03919091166000908152600560205260409020805460ff1916911515919091179055565b60008054820142101580156104c2575060015482014211155b92915050565b336000908152600360205260409020546104e290826111b2565b3360008181526003602052604090209190915561051590730309c98b1bffa350bcb3f9fb9780970ca32a506090836111da565b50565b60046020526000908152604090205481565b60015481565b60006001600160a01b0382167370e36f6bf80a52b3b46b3af8e106cc0ed743e8e414806104c25750506001600160a01b03167335a18000230da775cac24873d00ff85bccded5501490565b606033321461059c5760405162461bcd60e51b81526004016104179061359e565b3360009081526005602052604090205460ff16156105cc5760405162461bcd60e51b8152600401610417906135f3565b33600090815260036020526040902054806105f95760405162461bcd60e51b815260040161041790613618565b33600090815260046020526040902054610612906104a9565b61062e5760405162461bcd60e51b815260040161041790613403565b33600090815260036020526040808220829055805163db57925760e01b81529051606092730309c98b1bffa350bcb3f9fb9780970ca32a50609263db5792579260048083019392829003018186803b15801561068957600080fd5b505afa15801561069d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106c59190810190613086565b5090506060815167ffffffffffffffff811180156106e257600080fd5b5060405190808252806020026020018201604052801561070c578160200160208202803683370190505b50905060005b82518110156107c95782818151811061072757fe5b60200260200101516001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161075a9190613310565b60206040518083038186803b15801561077257600080fd5b505afa158015610786573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107aa919061323b565b8282815181106107b657fe5b6020908102919091010152600101610712565b50604051630852cd8d60e31b8152730309c98b1bffa350bcb3f9fb9780970ca32a5060906342966c68906108019086906004016137af565b600060405180830381600087803b15801561081b57600080fd5b505af115801561082f573d6000803e3d6000fd5b5050505060005b82518110156109b2576108eb82828151811061084e57fe5b602002602001015184838151811061086257fe5b60200260200101516001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016108959190613310565b60206040518083038186803b1580156108ad57600080fd5b505afa1580156108c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e5919061323b565b906111b2565b8282815181106108f757fe5b60200260200101818152505082818151811061090f57fe5b60200260200101516001600160a01b031663a9059cbb3384848151811061093257fe5b60200260200101516040518363ffffffff1660e01b8152600401610957929190613324565b602060405180830381600087803b15801561097157600080fd5b505af1158015610985573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a99190613110565b50600101610836565b509250505090565b6002546001600160a01b031681565b60005481565b6002546001600160a01b031633146109f95760405162461bcd60e51b8152600401610417906133bf565b600155565b6000333214610a1f5760405162461bcd60e51b81526004016104179061359e565b3360009081526005602052604090205460ff1615610a4f5760405162461bcd60e51b8152600401610417906135f3565b3360009081526003602052604090205480610a7c5760405162461bcd60e51b815260040161041790613618565b33600090815260046020526040902054610a95906104a9565b610ab15760405162461bcd60e51b815260040161041790613403565b33600090815260036020908152604080832092909255815160a0810183528a81528082018a90528083018990526060818101899052608082018890529251610af992016136d9565b6040516020818303038152906040529050610b1482826111f9565b506040516370a0823160e01b815260009073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2906370a0823190610b4f903090600401613310565b60206040518083038186803b158015610b6757600080fd5b505afa158015610b7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b9f919061323b565b905084811015610bc15760405162461bcd60e51b815260040161041790613575565b604051632e1a7d4d60e01b815273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d90610bf89084906004016137af565b600060405180830381600087803b158015610c1257600080fd5b505af1158015610c26573d6000803e3d6000fd5b505050506000336001600160a01b031682604051610c439061330d565b60006040518083038185875af1925050503d8060008114610c80576040519150601f19603f3d011682016040523d82523d6000602084013e610c85565b606091505b5050905080610ca65760405162461bcd60e51b81526004016104179061345e565b509998505050505050505050565b60006001600160a01b0382167312e51e77daaa58aa0e9247db7510ea4b46f9bead1480610cfd57506001600160a01b03821673328c4c80bc7aca0834db37e6600a6c49e12da4de145b80610d2457506001600160a01b038216737deb5e830be29f91e298ba5ff1356bb7f8146998145b80610d4b57506001600160a01b0382167369948cc03f478b95283f7dbf1ce764d0fc7ec54c145b806104c25750506001600160a01b0316739d91be44c06d373a8a226e1f3b146956083803eb1490565b610d94730309c98b1bffa350bcb3f9fb9780970ca32a5060333084611472565b33600090815260036020526040902054610dae9082611499565b33600090815260036020908152604080832093909355600490522042905550565b60006001600160a01b03821673f2db9a7c0acd427a680d640f02d90f6186e717251480610e1857506001600160a01b03821673fbeb78a723b8087fd2ea7ef1afec93d35e8bed42145b80610e3f57506001600160a01b03821673e14d13d8b3b85af791b2aadd661cdbd5e6097db1145b806104c25750506001600160a01b031673f29ae508698bdef169b89834f76704c3b205aedf1490565b604051631853304760e31b8152733d9819210a31b4961b30ef54be2aed79b9c9cd3b9063c299823890610e9f90849060040161337b565b600060405180830381600087803b158015610eb957600080fd5b505af1158015610ecd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261045091908101906130dd565b6002546001600160a01b03163314610f1f5760405162461bcd60e51b8152600401610417906133bf565b6001600160a01b038116730309c98b1bffa350bcb3f9fb9780970ca32a50601415610f5c5760405162461bcd60e51b8152600401610417906133e4565b6040516370a0823160e01b81526000906001600160a01b038316906370a0823190610f8b903090600401613310565b60206040518083038186803b158015610fa357600080fd5b505afa158015610fb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fdb919061323b565b600254909150610450906001600160a01b038481169116836111da565b6002546001600160a01b031633146110225760405162461bcd60e51b8152600401610417906133bf565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6002546001600160a01b0316331461106e5760405162461bcd60e51b8152600401610417906133bf565b600055565b60036020526000908152604090205481565b60056020526000908152604090205460ff1681565b8015806111225750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e906110d0903090869060040161333d565b60206040518083038186803b1580156110e857600080fd5b505afa1580156110fc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611120919061323b565b155b61113e5760405162461bcd60e51b815260040161041790613683565b6111948363095ea7b360e01b848460405160240161115d929190613324565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526114be565b505050565b60606111a8848460008561154d565b90505b9392505050565b6000828211156111d45760405162461bcd60e51b815260040161041790613485565b50900390565b6111948363a9059cbb60e01b848460405160240161115d929190613324565b6000611203612c13565b82806020019051810190611217919061312c565b90506060806112258661160e565b90925090506000805b83518110156113db5773c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031684828151811061126157fe5b60200260200101516001600160a01b0316141580156112a1575084518051600091908390811061128d57fe5b60200260200101516001600160a01b031614155b156113d3576112ef856000015182815181106112b957fe5b602002602001015160008684815181106112cf57fe5b60200260200101516001600160a01b031661109a9092919063ffffffff16565b61132a8560000151828151811061130257fe5b602002602001015184838151811061131657fe5b60200260200101518684815181106112cf57fe5b845180518290811061133857fe5b60200260200101516001600160a01b03168560200151828151811061135957fe5b602002602001015160405161136e91906132f1565b6000604051808303816000865af19150503d80600081146113ab576040519150601f19603f3d011682016040523d82523d6000602084013e6113b0565b606091505b505080925050816113d35760405162461bcd60e51b815260040161041790613502565b60010161122e565b506040516370a0823160e01b815260009073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2906370a0823190611416903090600401613310565b60206040518083038186803b15801561142e57600080fd5b505afa158015611442573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611466919061323b565b98975050505050505050565b611493846323b872dd60e01b85858560405160240161115d93929190613357565b50505050565b6000828201838110156111ab5760405162461bcd60e51b815260040161041790613427565b6060611513826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166111999092919063ffffffff16565b80519091501561119457808060200190518101906115319190613110565b6111945760405162461bcd60e51b815260040161041790613639565b60608247101561156f5760405162461bcd60e51b8152600401610417906134bc565b61157885611977565b6115945760405162461bcd60e51b8152600401610417906135bc565b60006060866001600160a01b031685876040516115b191906132f1565b60006040518083038185875af1925050503d80600081146115ee576040519150601f19603f3d011682016040523d82523d6000602084013e6115f3565b606091505b509150915061160382828661197d565b979650505050505050565b6060806060730309c98b1bffa350bcb3f9fb9780970ca32a50606001600160a01b031663db5792576040518163ffffffff1660e01b815260040160006040518083038186803b15801561166057600080fd5b505afa158015611674573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261169c9190810190613086565b5090506060815167ffffffffffffffff811180156116b957600080fd5b506040519080825280602002602001820160405280156116e3578160200160208202803683370190505b5090506060825167ffffffffffffffff8111801561170057600080fd5b5060405190808252806020026020018201604052801561172a578160200160208202803683370190505b5090506060835167ffffffffffffffff8111801561174757600080fd5b50604051908082528060200260200182016040528015611771578160200160208202803683370190505b50905060008060005b86518110156118315786818151811061178f57fe5b60200260200101516001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016117c29190613310565b60206040518083038186803b1580156117da57600080fd5b505afa1580156117ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611812919061323b565b86828151811061181e57fe5b602090810291909101015260010161177a565b50604051630852cd8d60e31b8152730309c98b1bffa350bcb3f9fb9780970ca32a5060906342966c6890611869908c906004016137af565b600060405180830381600087803b15801561188357600080fd5b505af1158015611897573d6000803e3d6000fd5b5050505060005b8651811015611967576118ca8682815181106118b657fe5b602002602001015188838151811061086257fe5b8682815181106118d657fe5b6020026020010181815250506119128782815181106118f157fe5b602002602001015187838151811061190557fe5b60200260200101516119b6565b80935081945050508285828151811061192757fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508184828151811061195457fe5b602090810291909101015260010161189e565b5092965090945050505050915091565b3b151590565b6060831561198c5750816111ab565b82511561199c5782518084602001fd5b8160405162461bcd60e51b815260040161041791906133ac565b6000806119c284610530565b156119da576119d18484611ea7565b91509150611ea0565b6119e384610cb4565b156119f2576119d184846120d6565b6001600160a01b038416738798249c2e607446efb7ad49ec89dd1865ff42721415611a20576119d18361225b565b6001600160a01b03841673cee60cfa923170e4f8204ae08b4fa6a3f5656f3a1415611a4e576119d1836123b5565b6001600160a01b03841673fd4d8a17df4c27c1dd245d153ccf4499e806c87d1415611a94576000611a7e8461258b565b915050611a8a816123b5565b9250925050611ea0565b6001600160a01b03841673f2db9a7c0acd427a680d640f02d90f6186e717251415611ac4576000611a7e84612730565b6001600160a01b038416739d409a0a012cfba9b15f6d4b36ac57a46966ab9a1480611b0b57506001600160a01b03841673c5bddf9843308380375a611c18b50fb9341f502a145b15611dda576001600160a01b03841673c5bddf9843308380375a611c18b50fb9341f502a1415611b3d57611b3d612885565b6040805160028082526060808301845292602083019080368337019050509050739d409a0a012cfba9b15f6d4b36ac57a46966ab9a81600081518110611b7f57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281600181518110611bc157fe5b6001600160a01b03909216602092830291909101909101526040516370a0823160e01b8152600090739d409a0a012cfba9b15f6d4b36ac57a46966ab9a906370a0823190611c13903090600401613310565b60206040518083038186803b158015611c2b57600080fd5b505afa158015611c3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c63919061323b565b60405163095ea7b360e01b8152909150739d409a0a012cfba9b15f6d4b36ac57a46966ab9a9063095ea7b390611cb39073d9e1ce17f2641f24ae83637ab66a2cca9c378b9f908590600401613324565b602060405180830381600087803b158015611ccd57600080fd5b505af1158015611ce1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d059190613110565b506040516338ed173960e01b815260609073d9e1ce17f2641f24ae83637ab66a2cca9c378b9f906338ed173990611d4c90859060009088903090603c4201906004016137b8565b600060405180830381600087803b158015611d6657600080fd5b505af1158015611d7a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611da291908101906130dd565b905073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281600181518110611dc657fe5b602002602001015194509450505050611ea0565b6001600160a01b03841673f2db9a7c0acd427a680d640f02d90f6186e717251480611e2157506001600160a01b03841673fbeb78a723b8087fd2ea7ef1afec93d35e8bed42145b80611e4857506001600160a01b03841673e14d13d8b3b85af791b2aadd661cdbd5e6097db1145b80611e6f57506001600160a01b03841673f29ae508698bdef169b89834f76704c3b205aedf145b15611e9a57600080611e818686612a01565b91509150611e8f82826119b6565b935093505050611ea0565b50829050815b9250929050565b6000806001600160a01b0384167335a18000230da775cac24873d00ff85bccded5501480611ef157506001600160a01b0384167370e36f6bf80a52b3b46b3af8e106cc0ed743e8e4145b611f0d5760405162461bcd60e51b815260040161041790613549565b836001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015611f4657600080fd5b505afa158015611f5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f7e9190612f23565b91506000826001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611fae9190613310565b60206040518083038186803b158015611fc657600080fd5b505afa158015611fda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ffe919061323b565b60405163db006a7560e01b81529091506001600160a01b0386169063db006a759061202d9087906004016137af565b602060405180830381600087803b15801561204757600080fd5b505af115801561205b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061207f919061323b565b1561209c5760405162461bcd60e51b815260040161041790613521565b6120cc81846001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016108959190613310565b9150509250929050565b600080836001600160a01b03166389d1a0fc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561211257600080fd5b505afa158015612126573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061214a9190612f23565b91506000826001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161217a9190613310565b60206040518083038186803b15801561219257600080fd5b505afa1580156121a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ca919061323b565b60405163db006a7560e01b81529091506001600160a01b0386169063db006a75906121f99087906004016137af565b600060405180830381600087803b15801561221357600080fd5b505af1158015612227573d6000803e3d6000fd5b505050506120cc81846001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016108959190613310565b6040516370a0823160e01b815260009081908190736b3595068778dd592e39a122f4f5a5cf09c90fe2906370a0823190612299903090600401613310565b60206040518083038186803b1580156122b157600080fd5b505afa1580156122c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122e9919061323b565b6040516367dfd4c960e01b8152909150738798249c2e607446efb7ad49ec89dd1865ff4272906367dfd4c9906123239087906004016137af565b600060405180830381600087803b15801561233d57600080fd5b505af1158015612351573d6000803e3d6000fd5b50506040516370a0823160e01b81526000925061239591508390736b3595068778dd592e39a122f4f5a5cf09c90fe2906370a0823190610895903090600401613310565b736b3595068778dd592e39a122f4f5a5cf09c90fe2945092505050915091565b6040516370a0823160e01b81526000908190819073514910771af9ca656af840dff83e8264ecf986ca906370a08231906123f3903090600401613310565b60206040518083038186803b15801561240b57600080fd5b505afa15801561241f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612443919061323b565b604051630d2680e960e11b815290915073f178c0b5bb7e7abf4e12a4838c7b7c5ba2c623c090631a4d01d29061248290879060009081906004016137f4565b602060405180830381600087803b15801561249c57600080fd5b505af11580156124b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124d4919061323b565b506040516370a0823160e01b815260009073514910771af9ca656af840dff83e8264ecf986ca906370a082319061250f903090600401613310565b60206040518083038186803b15801561252757600080fd5b505afa15801561253b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061255f919061323b565b905073514910771af9ca656af840dff83e8264ecf986ca61258082846111b2565b935093505050915091565b6040516370a0823160e01b81526000908190819073cee60cfa923170e4f8204ae08b4fa6a3f5656f3a906370a08231906125c9903090600401613310565b60206040518083038186803b1580156125e157600080fd5b505afa1580156125f5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612619919061323b565b604051632e1a7d4d60e01b815290915073fd4d8a17df4c27c1dd245d153ccf4499e806c87d90632e1a7d4d906126539087906004016137af565b600060405180830381600087803b15801561266d57600080fd5b505af1158015612681573d6000803e3d6000fd5b50506040516370a0823160e01b81526000925073cee60cfa923170e4f8204ae08b4fa6a3f5656f3a91506370a08231906126bf903090600401613310565b60206040518083038186803b1580156126d757600080fd5b505afa1580156126eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061270f919061323b565b905073cee60cfa923170e4f8204ae08b4fa6a3f5656f3a61258082846111b2565b6040516370a0823160e01b81526000908190819073cee60cfa923170e4f8204ae08b4fa6a3f5656f3a906370a082319061276e903090600401613310565b60206040518083038186803b15801561278657600080fd5b505afa15801561279a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127be919061323b565b604051632e1a7d4d60e01b815290915073f2db9a7c0acd427a680d640f02d90f6186e7172590632e1a7d4d906127f89087906004016137af565b602060405180830381600087803b15801561281257600080fd5b505af1158015612826573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061284a919061323b565b506040516370a0823160e01b815260009073cee60cfa923170e4f8204ae08b4fa6a3f5656f3a906370a08231906126bf903090600401613310565b6040516370a0823160e01b815260009073c5bddf9843308380375a611c18b50fb9341f502a906370a08231906128bf903090600401613310565b60206040518083038186803b1580156128d757600080fd5b505afa1580156128eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061290f919061323b565b905061294573c5bddf9843308380375a611c18b50fb9341f502a739d409a0a012cfba9b15f6d4b36ac57a46966ab9a600061109a565b61297873c5bddf9843308380375a611c18b50fb9341f502a739d409a0a012cfba9b15f6d4b36ac57a46966ab9a8361109a565b60405163b6b55f2560e01b8152739d409a0a012cfba9b15f6d4b36ac57a46966ab9a9063b6b55f25906129af9084906004016137af565b602060405180830381600087803b1580156129c957600080fd5b505af11580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610450919061323b565b6000806000846001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b158015612a3f57600080fd5b505afa158015612a53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a779190612f23565b90506000816001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401612aa79190613310565b60206040518083038186803b158015612abf57600080fd5b505afa158015612ad3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612af7919061323b565b604051632e1a7d4d60e01b81529091506001600160a01b03871690632e1a7d4d90612b269088906004016137af565b602060405180830381600087803b158015612b4057600080fd5b505af1158015612b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b78919061323b565b506040516370a0823160e01b81526000906001600160a01b038416906370a0823190612ba8903090600401613310565b60206040518083038186803b158015612bc057600080fd5b505afa158015612bd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bf8919061323b565b905082612c0582846111b2565b945094505050509250929050565b6040518060a0016040528060608152602001606081526020016060815260200160608152602001606081525090565b600082601f830112612c52578081fd5b8135612c65612c6082613831565b61380d565b818152915060208083019084810181840286018201871015612c8657600080fd5b60005b84811015612cae578135612c9c8161389d565b84529282019290820190600101612c89565b505050505092915050565b600082601f830112612cc9578081fd5b8151612cd7612c6082613831565b818152915060208083019084810181840286018201871015612cf857600080fd5b60005b84811015612cae578151612d0e8161389d565b84529282019290820190600101612cfb565b600082601f830112612d30578081fd5b8135612d3e612c6082613831565b818152915060208083019084810160005b84811015612cae578135870188603f820112612d6a57600080fd5b83810135612d7a612c608261384f565b81815260408b81848601011115612d9057600080fd5b82818501888401375060009181018601919091528552509282019290820190600101612d4f565b600082601f830112612dc7578081fd5b8151612dd5612c6082613831565b818152915060208083019084810160005b84811015612cae578151870188603f820112612e0157600080fd5b83810151612e11612c608261384f565b81815260408b81848601011115612e2757600080fd5b612e3683888401838701613871565b50865250509282019290820190600101612de6565b600082601f830112612e5b578081fd5b8135612e69612c6082613831565b818152915060208083019084810181840286018201871015612e8a57600080fd5b60005b84811015612cae57813584529282019290820190600101612e8d565b600082601f830112612eb9578081fd5b8151612ec7612c6082613831565b818152915060208083019084810181840286018201871015612ee857600080fd5b60005b84811015612cae57815184529282019290820190600101612eeb565b600060208284031215612f18578081fd5b81356111ab8161389d565b600060208284031215612f34578081fd5b81516111ab8161389d565b60008060408385031215612f51578081fd5b8235612f5c8161389d565b91506020830135612f6c816138b2565b809150509250929050565b600060208284031215612f88578081fd5b813567ffffffffffffffff811115612f9e578182fd5b612faa84828501612c42565b949350505050565b60008060008060008060c08789031215612fca578182fd5b863567ffffffffffffffff80821115612fe1578384fd5b612fed8a838b01612c42565b97506020890135915080821115613002578384fd5b61300e8a838b01612d20565b96506040890135915080821115613023578384fd5b61302f8a838b01612c42565b95506060890135915080821115613044578384fd5b6130508a838b01612c42565b94506080890135915080821115613065578384fd5b5061307289828a01612e4b565b92505060a087013590509295509295509295565b60008060408385031215613098578182fd5b825167ffffffffffffffff808211156130af578384fd5b6130bb86838701612cb9565b935060208501519150808211156130d0578283fd5b506120cc85828601612ea9565b6000602082840312156130ee578081fd5b815167ffffffffffffffff811115613104578182fd5b612faa84828501612ea9565b600060208284031215613121578081fd5b81516111ab816138b2565b60006020828403121561313d578081fd5b815167ffffffffffffffff80821115613154578283fd5b9083019060a08286031215613167578283fd5b61317160a061380d565b82518281111561317f578485fd5b61318b87828601612cb9565b82525060208301518281111561319f578485fd5b6131ab87828601612db7565b6020830152506040830151828111156131c2578485fd5b6131ce87828601612cb9565b6040830152506060830151828111156131e5578485fd5b6131f187828601612cb9565b606083015250608083015182811115613208578485fd5b61321487828601612ea9565b60808301525095945050505050565b600060208284031215613234578081fd5b5035919050565b60006020828403121561324c578081fd5b5051919050565b6000815180845260208085019450808401835b8381101561328b5781516001600160a01b031687529582019590820190600101613266565b509495945050505050565b6000815180845260208085019450808401835b8381101561328b578151875295820195908201906001016132a9565b600081518084526132dd816020860160208601613871565b601f01601f19169290920160200192915050565b60008251613303818460208701613871565b9190910192915050565b90565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6000602082526111ab6020830184613253565b6000602082526111ab6020830184613296565b901515815260200190565b6000602082526111ab60208301846132c5565b6020808252600b908201526a21676f7665726e616e636560a81b604082015260600190565b602080825260059082015264216264706960d81b604082015260600190565b6020808252600a908201526902174696d657374616d760b41b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252600d908201526c10b2ba3416ba3930b739b332b960991b604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b602080825260059082015264021737761760dc1b604082015260600190565b6020808252600e908201526d2163746f6b656e2d72656465656d60901b604082015260600190565b60208082526012908201527110bb30b634b216b33937b696b1ba37b5b2b760711b604082015260600190565b6020808252600f908201526e085b5a5b8b595d1a0b585b5bdd5b9d608a1b604082015260600190565b60208082526004908201526321656f6160e01b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a189b1858dadb1a5cdd195960aa1b604082015260600190565b60208082526007908201526608585b5bdd5b9d60ca1b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606082015260800190565b60006020808352835160a0828501526136f560c0850182613253565b82860151601f19868303810160408801528151808452929350908401918385019080860285018601875b8281101561374b57848783030184526137398287516132c5565b9588019593880193915060010161371f565b5060408a01519650838982030160608a01526137678188613253565b965050505060608701519250808685030160808701526137878484613253565b935060808701519250808685030160a087015250506137a68282613296565b95945050505050565b90815260200190565b600086825285602083015260a060408301526137d760a0830186613253565b6001600160a01b0394909416606083015250608001529392505050565b928352600f9190910b6020830152604082015260600190565b60405181810167ffffffffffffffff8111828210171561382957fe5b604052919050565b600067ffffffffffffffff82111561384557fe5b5060209081020190565b600067ffffffffffffffff82111561386357fe5b50601f01601f191660200190565b60005b8381101561388c578181015183820152602001613874565b838111156114935750506000910152565b6001600160a01b038116811461051557600080fd5b801515811461051557600080fdfea26469706673582212202b1c2a16b490a272394d6728ea3eeba1c311f65b6bcfce87bc61bfce987b34b264736f6c63430007030033

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

000000000000000000000000f337a885a7543cab542b2d3f5a8c1945036e0c42

-----Decoded View---------------
Arg [0] : _governance (address): 0xF337A885a7543CAb542B2D3f5A8c1945036E0C42

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000f337a885a7543cab542b2d3f5a8c1945036e0c42


Deployed Bytecode Sourcemap

302:4935:4:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1845:172;;;;;;;;;;-1:-1:-1;1845:172:4;;;;;:::i;:::-;;:::i;:::-;;2253:103;;;;;;;;;;-1:-1:-1;2253:103:4;;;;;:::i;:::-;;:::i;5025:210::-;;;;;;;;;;-1:-1:-1;5025:210:4;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2688:181;;;;;;;;;;-1:-1:-1;2688:181:4;;;;;:::i;:::-;;:::i;759:57::-;;;;;;;;;;-1:-1:-1;759:57:4;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;564:41::-;;;;;;;;;;;;;:::i;9231:124:2:-;;;;;;;;;;-1:-1:-1;9231:124:2;;;;;:::i;:::-;;:::i;2901:827:4:-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;628:25::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;520:38::-;;;;;;;;;;;;;:::i;2135:112::-;;;;;;;;;;-1:-1:-1;2135:112:4;;;;;:::i;:::-;;:::i;3734:1254::-;;;;;;;;;;-1:-1:-1;3734:1254:4;;;;;:::i;:::-;;:::i;8889:192:2:-;;;;;;;;;;-1:-1:-1;8889:192:2;;;;;:::i;:::-;;:::i;2391:261:4:-;;;;;;;;;;-1:-1:-1;2391:261:4;;;;;:::i;:::-;;:::i;9504:167:2:-;;;;;;;;;;-1:-1:-1;9504:167:2;;;;;:::i;:::-;;:::i;4931:121::-;;;;;;;;;;-1:-1:-1;4931:121:2;;;;;:::i;:::-;;:::i;1604:235:4:-;;;;;;;;;;-1:-1:-1;1604:235:4;;;;;:::i;:::-;;:::i;1505:93::-;;;;;;;;;;-1:-1:-1;1505:93:4;;;;;:::i;:::-;;:::i;2023:106::-;;;;;;;;;;-1:-1:-1;2023:106:4;;;;;:::i;:::-;;:::i;682:43::-;;;;;;;;;;-1:-1:-1;682:43:4;;;;;:::i;:::-;;:::i;840:45::-;;;;;;;;;;-1:-1:-1;840:45:4;;;;;:::i;:::-;;:::i;1845:172::-;1213:10;;-1:-1:-1;;;;;1213:10:4;1199;:24;1191:48;;;;-1:-1:-1;;;1191:48:4;;;;;;;:::i;:::-;;;;;;;;;1923:9:::1;1918:93;1942:7;:14;1938:1;:18;1918:93;;;1977:23;1989:7;1997:1;1989:10;;;;;;;;;;;;;;1977:11;:23::i;:::-;1958:3;;1918:93;;;;1845:172:::0;:::o;2253:103::-;1213:10;;-1:-1:-1;;;;;1213:10:4;1199;:24;1191:48;;;;-1:-1:-1;;;1191:48:4;;;;;;;:::i;:::-;-1:-1:-1;;;;;2324:20:4;;;::::1;;::::0;;;:13:::1;:20;::::0;;;;:25;;-1:-1:-1;;2324:25:4::1;::::0;::::1;;::::0;;;::::1;::::0;;2253:103::o;5025:210::-;5086:4;5155:16;;5140:12;:31;5121:15;:50;;:107;;;;;5209:19;;5194:12;:34;5175:15;:53;;5121:107;5102:126;5025:210;-1:-1:-1;;5025:210:4:o;2688:181::-;2772:10;2763:20;;;;:8;:20;;;;;;:33;;2788:7;2763:24;:33::i;:::-;2749:10;2740:20;;;;:8;:20;;;;;:56;;;;2807:55;;4730:42:2;;2854:7:4;2807:34;:55::i;:::-;2688:181;:::o;759:57::-;;;;;;;;;;;;;:::o;564:41::-;;;;:::o;9231:124:2:-;9288:4;-1:-1:-1;;;;;9312:16:2;;2821:42;9312:16;;:35;;-1:-1:-1;;;;;;;9332:15:2;2748:42;9332:15;;9231:124::o;2901:827:4:-;2956:16;1300:10;1314:9;1300:23;1292:40;;;;-1:-1:-1;;;1292:40:4;;;;;;;:::i;:::-;1415:10:::1;1401:25;::::0;;;:13:::1;:25;::::0;;;;;::::1;;1400:26;1392:50;;;;-1:-1:-1::0;;;1392:50:4::1;;;;;;;:::i;:::-;3011:10:::2;2984:15;3002:20:::0;;;:8:::2;:20;::::0;;;;;3041:11;3033:31:::2;;;;-1:-1:-1::0;;;3033:31:4::2;;;;;;;:::i;:::-;3114:10;3091:34;::::0;;;:22:::2;:34;::::0;;;;;3082:44:::2;::::0;:8:::2;:44::i;:::-;3074:67;;;;-1:-1:-1::0;;;3074:67:4::2;;;;;;;:::i;:::-;3161:10;3175:1;3152:20:::0;;;:8:::2;:20;::::0;;;;;:24;;;3217:36;;-1:-1:-1;;;3217:36:4;;;;3188:23:::2;::::0;4730:42:2::2;::::0;3217:34:4::2;::::0;:36:::2;::::0;;::::2;::::0;3175:1;3217:36;;;;;4730:42:2;3217:36:4;::::2;;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;::::0;;::::2;-1:-1:-1::0;;3217:36:4::2;::::0;::::2;;::::0;::::2;::::0;;;::::2;::::0;::::2;:::i;:::-;3187:66;;;3263:23;3303:6;:13;3289:28;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;3289:28:4::2;;3263:54;;3333:9;3328:123;3352:6;:13;3348:1;:17;3328:123;;;3405:6;3412:1;3405:9;;;;;;;;;;;;;;-1:-1:-1::0;;;;;3398:27:4::2;;3434:4;3398:42;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3386:6;3393:1;3386:9;;;;;;;;;::::0;;::::2;::::0;;;;;:54;3367:3:::2;;3328:123;;;-1:-1:-1::0;3460:27:4::2;::::0;-1:-1:-1;;;3460:27:4;;4730:42:2::2;::::0;3460:18:4::2;::::0;:27:::2;::::0;3479:7;;3460:27:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;3502:9;3497:201;3521:6;:13;3517:1;:17;3497:201;;;3567:57;3614:6;3621:1;3614:9;;;;;;;;;;;;;;3574:6;3581:1;3574:9;;;;;;;;;;;;;;-1:-1:-1::0;;;;;3567:27:4::2;;3603:4;3567:42;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:46:::0;::::2;:57::i;:::-;3555:6;3562:1;3555:9;;;;;;;;;;;;;:69;;;::::0;::::2;3645:6;3652:1;3645:9;;;;;;;;;;;;;;-1:-1:-1::0;;;;;3638:26:4::2;;3665:10;3677:6;3684:1;3677:9;;;;;;;;;;;;;;3638:49;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;3536:3:4::2;;3497:201;;;-1:-1:-1::0;3715:6:4;-1:-1:-1;;;2901:827:4;:::o;628:25::-;;;-1:-1:-1;;;;;628:25:4;;:::o;520:38::-;;;;:::o;2135:112::-;1213:10;;-1:-1:-1;;;;;1213:10:4;1199;:24;1191:48;;;;-1:-1:-1;;;1191:48:4;;;;;;;:::i;:::-;2210:19:::1;:30:::0;2135:112::o;3734:1254::-;4024:7;1300:10;1314:9;1300:23;1292:40;;;;-1:-1:-1;;;1292:40:4;;;;;;;:::i;:::-;1415:10:::1;1401:25;::::0;;;:13:::1;:25;::::0;;;;;::::1;;1400:26;1392:50;;;;-1:-1:-1::0;;;1392:50:4::1;;;;;;;:::i;:::-;4070:10:::2;4043:15;4061:20:::0;;;:8:::2;:20;::::0;;;;;4100:11;4092:31:::2;;;;-1:-1:-1::0;;;4092:31:4::2;;;;;;;:::i;:::-;4173:10;4150:34;::::0;;;:22:::2;:34;::::0;;;;;4141:44:::2;::::0;:8:::2;:44::i;:::-;4133:67;;;;-1:-1:-1::0;;;4133:67:4::2;;;;;;;:::i;:::-;4220:10;4234:1;4211:20:::0;;;:8:::2;:20;::::0;;;;;;;:24;;;;4328:272;;::::2;::::0;::::2;::::0;;;;;;;::::2;::::0;;;;;;;;;4264:21:::2;4328:272:::0;;;;;;;;;;;;4300:314;;::::2;::::0;::::2;;:::i;:::-;;;;;;;;;;;;;4264:350;;4637:33;4652:7;4661:8;4637:14;:33::i;:::-;-1:-1:-1::0;4700:37:4::2;::::0;-1:-1:-1;;;4700:37:4;;4680:17:::2;::::0;2994:42:2::2;::::0;4700:22:4::2;::::0;:37:::2;::::0;4731:4:::2;::::0;4700:37:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4680:57;;4768:13;4755:9;:26;;4747:54;;;;-1:-1:-1::0;;;4747:54:4::2;;;;;;;:::i;:::-;4811:31;::::0;-1:-1:-1;;;4811:31:4;;2994:42:2::2;::::0;4811:20:4::2;::::0;:31:::2;::::0;4832:9;;4811:31:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;4854:12;4872:10;-1:-1:-1::0;;;;;4872:15:4::2;4896:9;4872:39;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4853:58;;;4929:7;4921:33;;;;-1:-1:-1::0;;;4921:33:4::2;;;;;;;:::i;:::-;-1:-1:-1::0;4972:9:4;3734:1254;-1:-1:-1;;;;;;;;;3734:1254:4:o;8889:192:2:-;8948:4;-1:-1:-1;;;;;8972:17:2;;4341:42;8972:17;;:38;;-1:-1:-1;;;;;;8993:17:2;;4415:42;8993:17;8972:38;:59;;;-1:-1:-1;;;;;;9014:17:2;;4489:42;9014:17;8972:59;:80;;;-1:-1:-1;;;;;;9035:17:2;;4563:42;9035:17;8972:80;:101;;;-1:-1:-1;;;;;;;9056:17:2;4637:42;9056:17;;8889:192::o;2391:261:4:-;2442:74;4730:42:2;2481:10:4;2501:4;2508:7;2442:38;:74::i;:::-;2559:10;2550:20;;;;:8;:20;;;;;;:33;;2575:7;2550:24;:33::i;:::-;2536:10;2527:20;;;;:8;:20;;;;;;;;:56;;;;2593:22;:34;;;2630:15;2593:52;;-1:-1:-1;2391:261:4:o;9504:167:2:-;9561:4;-1:-1:-1;;;;;9585:21:2;;2292:42;9585:21;;:40;;-1:-1:-1;;;;;;9610:15:2;;2514:42;9610:15;9585:40;:59;;;-1:-1:-1;;;;;;9629:15:2;;2587:42;9629:15;9585:59;:78;;;-1:-1:-1;;;;;;;9648:15:2;2660:42;9648:15;;9504:167::o;4931:121::-;4997:48;;-1:-1:-1;;;4997:48:2;;1726:42;;4997:38;;:48;;5036:8;;4997:48;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4997:48:2;;;;;;;;;;;;:::i;1604:235:4:-;1213:10;;-1:-1:-1;;;;;1213:10:4;1199;:24;1191:48;;;;-1:-1:-1;;;1191:48:4;;;;;;;:::i;:::-;-1:-1:-1;;;;;1674:23:4;::::1;4730:42:2;1674:23:4;;1666:41;;;;-1:-1:-1::0;;;1666:41:4::1;;;;;;;:::i;:::-;1735:39;::::0;-1:-1:-1;;;1735:39:4;;1717:15:::1;::::0;-1:-1:-1;;;;;1735:24:4;::::1;::::0;::::1;::::0;:39:::1;::::0;1768:4:::1;::::0;1735:39:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1812:10;::::0;1717:57;;-1:-1:-1;1784:48:4::1;::::0;-1:-1:-1;;;;;1784:27:4;;::::1;::::0;1812:10:::1;1717:57:::0;1784:27:::1;:48::i;1505:93::-:0;1213:10;;-1:-1:-1;;;;;1213:10:4;1199;:24;1191:48;;;;-1:-1:-1;;;1191:48:4;;;;;;;:::i;:::-;1567:10:::1;:24:::0;;-1:-1:-1;;;;;;1567:24:4::1;-1:-1:-1::0;;;;;1567:24:4;;;::::1;::::0;;;::::1;::::0;;1505:93::o;2023:106::-;1213:10;;-1:-1:-1;;;;;1213:10:4;1199;:24;1191:48;;;;-1:-1:-1;;;1191:48:4;;;;;;;:::i;:::-;2095:16:::1;:27:::0;2023:106::o;682:43::-;;;;;;;;;;;;;:::o;840:45::-;;;;;;;;;;;;;;;:::o;1329:613:17:-;1694:10;;;1693:62;;-1:-1:-1;1710:39:17;;-1:-1:-1;;;1710:39:17;;-1:-1:-1;;;;;1710:15:17;;;;;:39;;1734:4;;1741:7;;1710:39;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;1693:62;1685:150;;;;-1:-1:-1;;;1685:150:17;;;;;;;:::i;:::-;1845:90;1865:5;1895:22;;;1919:7;1928:5;1872:62;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;1872:62:17;;;;;;;;;;;;;;-1:-1:-1;;;;;1872:62:17;-1:-1:-1;;;;;;1872:62:17;;;;;;;;;;1845:19;:90::i;:::-;1329:613;;;:::o;3581:193:1:-;3684:12;3715:52;3737:6;3745:4;3751:1;3754:12;3715:21;:52::i;:::-;3708:59;;3581:193;;;;;;:::o;3136:155:18:-;3194:7;3226:1;3221;:6;;3213:49;;;;-1:-1:-1;;;3213:49:18;;;;;;;:::i;:::-;-1:-1:-1;3279:5:18;;;3136:155::o;685:175:17:-;767:86;787:5;817:23;;;842:2;846:5;794:58;;;;;;;;;:::i;20088:1003:2:-;20172:7;20191:24;;:::i;:::-;20229:7;20218:31;;;;;;;;;;;;:::i;:::-;20191:58;;20261:28;20291:34;20341:46;20376:10;20341:34;:46::i;:::-;20260:127;;-1:-1:-1;20260:127:2;-1:-1:-1;20436:12:2;;20458:533;20482:11;:18;20478:1;:22;20458:533;;;2994:42;-1:-1:-1;;;;;20607:22:2;:11;20619:1;20607:14;;;;;;;;;;;;;;-1:-1:-1;;;;;20607:22:2;;;:59;;;;-1:-1:-1;20633:16:2;;:19;;20664:1;;20633:16;20650:1;;20633:19;;;;;;;;;;;;-1:-1:-1;;;;;20633:33:2;;;20607:59;20603:378;;;20686:58;20721:8;:16;;;20738:1;20721:19;;;;;;;;;;;;;;20742:1;20693:11;20705:1;20693:14;;;;;;;;;;;;;;-1:-1:-1;;;;;20686:34:2;;;:58;;;;;:::i;:::-;20762:77;20797:8;:16;;;20814:1;20797:19;;;;;;;;;;;;;;20818:17;20836:1;20818:20;;;;;;;;;;;;;;20769:11;20781:1;20769:14;;;;;;;20762:77;20871:16;;:19;;20888:1;;20871:19;;;;;;;;;;;;-1:-1:-1;;;;;20871:24:2;20896:8;:23;;;20920:1;20896:26;;;;;;;;;;;;;;20871:52;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20857:66;;;;;20949:7;20941:25;;;;-1:-1:-1;;;20941:25:2;;;;;;;:::i;:::-;20502:3;;20458:533;;;-1:-1:-1;21021:37:2;;-1:-1:-1;;;21021:37:2;;21001:17;;2994:42;;21021:22;;:37;;21052:4;;21021:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;21001:57;20088:1003;-1:-1:-1;;;;;;;;20088:1003:2:o;866:203:17:-;966:96;986:5;1016:27;;;1045:4;1051:2;1055:5;993:68;;;;;;;;;;:::i;966:96::-;866:203;;;;:::o;2690:175:18:-;2748:7;2779:5;;;2802:6;;;;2794:46;;;;-1:-1:-1;;;2794:46:18;;;;;;;:::i;2948:751:17:-;3367:23;3393:69;3421:4;3393:69;;;;;;;;;;;;;;;;;3401:5;-1:-1:-1;;;;;3393:27:17;;;:69;;;;;:::i;:::-;3476:17;;3367:95;;-1:-1:-1;3476:21:17;3472:221;;3616:10;3605:30;;;;;;;;;;;;:::i;:::-;3597:85;;;;-1:-1:-1;;;3597:85:17;;;;;;;:::i;4608:523:1:-;4735:12;4792:5;4767:21;:30;;4759:81;;;;-1:-1:-1;;;4759:81:1;;;;;;;:::i;:::-;4858:18;4869:6;4858:10;:18::i;:::-;4850:60;;;;-1:-1:-1;;;4850:60:1;;;;;;;:::i;:::-;4981:12;4995:23;5022:6;-1:-1:-1;;;;;5022:11:1;5042:5;5050:4;5022:33;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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;21097:1040:2:-;21195:16;21213;21246:23;4730:42;-1:-1:-1;;;;;21275:34:2;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;21275:36:2;;;;;;;;;;;;:::i;:::-;21245:66;;;21321:23;21361:6;:13;21347:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;21347:28:2;;21321:54;;21385:28;21430:6;:13;21416:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;21416:28:2;;21385:59;;21454:34;21505:6;:13;21491:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;21491:28:2;;21454:65;;21530:18;21558:24;21598:9;21593:123;21617:6;:13;21613:1;:17;21593:123;;;21670:6;21677:1;21670:9;;;;;;;;;;;;;;-1:-1:-1;;;;;21663:27:2;;21699:4;21663:42;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;21651:6;21658:1;21651:9;;;;;;;;;;;;;;;;;:54;21632:3;;21593:123;;;-1:-1:-1;21725:30:2;;-1:-1:-1;;;21725:30:2;;4730:42;;21725:18;;:30;;21744:10;;21725:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21770:9;21765:316;21789:6;:13;21785:1;:17;21765:316;;;21835:57;21882:6;21889:1;21882:9;;;;;;;;;;;;;;21842:6;21849:1;21842:9;;;;;;;21835:57;21823:6;21830:1;21823:9;;;;;;;;;;;;;:69;;;;;21940:35;21954:6;21961:1;21954:9;;;;;;;;;;;;;;21965:6;21972:1;21965:9;;;;;;;;;;;;;;21940:13;:35::i;:::-;21907:68;;;;;;;;22007:10;21990:11;22002:1;21990:14;;;;;;;;;;;;;:27;-1:-1:-1;;;;;21990:27:2;;;-1:-1:-1;;;;;21990:27:2;;;;;22054:16;22031:17;22049:1;22031:20;;;;;;;;;;;;;;;;;:39;21804:3;;21765:316;;;-1:-1:-1;22099:11:2;;-1:-1:-1;22112:17:2;;-1:-1:-1;;;;;21097:1040:2;;;:::o;726:413:1:-;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;;;;;;;;:::i;5272:1959:2:-;5352:7;5361;5384:23;5394:12;5384:9;:23::i;:::-;5380:95;;;5430:34;5442:12;5456:7;5430:11;:34::i;:::-;5423:41;;;;;;5380:95;5489:25;5501:12;5489:11;:25::i;:::-;5485:99;;;5537:36;5551:12;5565:7;5537:13;:36::i;5485:99::-;-1:-1:-1;;;;;5598:22:2;;2909:42;5598:22;5594:80;;;5643:20;5655:7;5643:11;:20::i;5594:80::-;-1:-1:-1;;;;;5688:23:2;;1847:42;5688:23;5684:82;;;5734:21;5747:7;5734:12;:21::i;5684:82::-;-1:-1:-1;;;;;5780:28:2;;1927:42;5780:28;5776:147;;;5827:14;5845:26;5863:7;5845:17;:26::i;:::-;5824:47;;;5892:20;5905:6;5892:12;:20::i;:::-;5885:27;;;;;;;5776:147;-1:-1:-1;;;;;5937:27:2;;2292:42;5937:27;5933:146;;;5983:14;6001:26;6019:7;6001:17;:26::i;5933:146::-;-1:-1:-1;;;;;6093:23:2;;2441:42;6093:23;;:49;;-1:-1:-1;;;;;;6120:22:2;;2366:42;6120:22;6093:49;6089:778;;;-1:-1:-1;;;;;6162:22:2;;2366:42;6162:22;6158:74;;;6204:13;:11;:13::i;:::-;6315:16;;;6329:1;6315:16;;;6291:21;6315:16;;;;;6291:21;6315:16;;;;;;;;;;-1:-1:-1;6315:16:2;6291:40;;2441:42;6345:4;6350:1;6345:7;;;;;;;;;;;;;:17;-1:-1:-1;;;;;6345:17:2;;;-1:-1:-1;;;;;6345:17:2;;;;;2994:42;6376:4;6381:1;6376:7;;;;;;;;-1:-1:-1;;;;;6376:14:2;;;:7;;;;;;;;;;;:14;6424:40;;-1:-1:-1;;;6424:40:2;;6405:16;;2441:42;;6424:25;;:40;;6458:4;;6424:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6479:51;;-1:-1:-1;;;6479:51:2;;6405:59;;-1:-1:-1;2441:42:2;;6479:23;;:51;;2119:42;;6405:59;;6479:51;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;6584:235:2;;-1:-1:-1;;;6584:235:2;;6544:21;;2119:42;;6584:61;;:235;;6667:8;;6697:1;;6720:4;;6754;;6799:2;6781:15;:20;;6584:235;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;6584:235:2;;;;;;;;;;;;:::i;:::-;6544:275;;2994:42;6848:4;6853:1;6848:7;;;;;;;;;;;;;;6834:22;;;;;;;;;6089:778;-1:-1:-1;;;;;6898:27:2;;2292:42;6898:27;;:52;;-1:-1:-1;;;;;;6929:21:2;;2514:42;6929:21;6898:52;:77;;;-1:-1:-1;;;;;;6954:21:2;;2587:42;6954:21;6898:77;:102;;;-1:-1:-1;;;;;;6979:21:2;;2660:42;6979:21;6898:102;6894:290;;;7017:24;7043:20;7067:40;7085:12;7099:7;7067:17;:40::i;:::-;7016:91;;;;7128:45;7142:16;7160:12;7128:13;:45::i;:::-;7121:52;;;;;;;;6894:290;-1:-1:-1;7202:12:2;;-1:-1:-1;7216:7:2;5272:1959;;;;;;:::o;10419:488::-;10493:14;;-1:-1:-1;;;;;10580:15:2;;2748:42;10580:15;;:35;;-1:-1:-1;;;;;;10599:16:2;;2821:42;10599:16;10580:35;10572:66;;;;-1:-1:-1;;;10572:66:2;;;;;;;:::i;:::-;10666:7;-1:-1:-1;;;;;10658:27:2;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;10649:38;;10698:14;10722:6;-1:-1:-1;;;;;10715:24:2;;10748:4;10715:39;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;10772:33;;-1:-1:-1;;;10772:33:2;;10698:56;;-1:-1:-1;;;;;;10772:23:2;;;;;:33;;10796:8;;10772:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:38;10764:65;;;;-1:-1:-1;;;10764:65:2;;;;;;;:::i;:::-;10849:51;10893:6;10856;-1:-1:-1;;;;;10849:24:2;;10882:4;10849:39;;;;;;;;;;;;;;;:::i;:51::-;10839:61;;10419:488;;;;;;:::o;11559:361::-;11635:14;11651:15;11697:7;-1:-1:-1;;;;;11687:41:2;;:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;11678:52;;11741:14;11765:6;-1:-1:-1;;;;;11758:24:2;;11791:4;11758:39;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;11807:35;;-1:-1:-1;;;11807:35:2;;11741:56;;-1:-1:-1;;;;;;11807:25:2;;;;;:35;;11833:8;;11807:35;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11862:51;11906:6;11869;-1:-1:-1;;;;;11862:24:2;;11895:4;11862:39;;;;;;;;;;;;;;;:::i;16638:307::-;16745:38;;-1:-1:-1;;;16745:38:2;;16700:7;;;;;;4177:42;;16745:23;;:38;;16777:4;;16745:38;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;16793;;-1:-1:-1;;;16793:38:2;;16728:55;;-1:-1:-1;2909:42:2;;16793:23;;:38;;16817:13;;16793:38;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;16857:38:2;;-1:-1:-1;;;16857:38:2;;16841:13;;-1:-1:-1;16857:50:2;;-1:-1:-1;16900:6:2;;4177:42;;16857:23;;:38;;16889:4;;16857:38;;;:::i;:50::-;4177:42;;-1:-1:-1;16841:66:2;-1:-1:-1;;;16638:307:2;;;:::o;12340:335::-;12444:37;;-1:-1:-1;;;12444:37:2;;12398:7;;;;;;3250:42;;12444:22;;:37;;12475:4;;12444:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12491:69;;-1:-1:-1;;;12491:69:2;;12426:55;;-1:-1:-1;1630:42:2;;12491:53;;:69;;12545:8;;12555:1;;;;12491:69;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;12587:37:2;;-1:-1:-1;;;12587:37:2;;12570:14;;3250:42;;12587:22;;:37;;12618:4;;12587:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12570:54;-1:-1:-1;3250:42:2;12648:19;12570:54;12659:7;12648:10;:19::i;:::-;12634:34;;;;;;12340:335;;;:::o;13091:351::-;13229:40;;-1:-1:-1;;;13229:40:2;;13153:7;;;;;;1847:42;;13229:25;;:40;;13263:4;;13229:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13279:42;;-1:-1:-1;;;13279:42:2;;13211:58;;-1:-1:-1;1927:42:2;;13279:33;;:42;;13313:7;;13279:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;13348:40:2;;-1:-1:-1;;;13348:40:2;;13331:14;;-1:-1:-1;1847:42:2;;-1:-1:-1;13348:25:2;;:40;;13382:4;;13348:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13331:57;-1:-1:-1;1847:42:2;13415:19;13331:57;13426:7;13415:10;:19::i;14428:316::-;14536:40;;-1:-1:-1;;;14536:40:2;;14490:7;;;;;;1847:42;;14536:25;;:40;;14570:4;;14536:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14586:37;;-1:-1:-1;;;14586:37:2;;14518:58;;-1:-1:-1;2292:42:2;;14586:28;;:37;;14615:7;;14586:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;14650:40:2;;-1:-1:-1;;;14650:40:2;;14633:14;;1847:42;;14650:25;;:40;;14684:4;;14650:40;;;:::i;13789:250::-;13849:39;;-1:-1:-1;;;13849:39:2;;13831:15;;2366:42;;13849:24;;:39;;13882:4;;13849:39;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13831:57;-1:-1:-1;13898:38:2;2366:42;2441;13934:1;13898:26;:38::i;:::-;13946:44;2366:42;2441;13982:7;13946:26;:44::i;:::-;14000:32;;-1:-1:-1;;;14000:32:2;;2441:42;;14000:23;;:32;;14024:7;;14000:32;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;15524:393::-;15602:7;15611;15630:19;15659:6;-1:-1:-1;;;;;15652:20:2;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;15630:44;;15684:15;15709:11;-1:-1:-1;;;;;15702:29:2;;15740:4;15702:44;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;15756:32;;-1:-1:-1;;;15756:32:2;;15684:62;;-1:-1:-1;;;;;;15756:23:2;;;;;:32;;15780:7;;15756:32;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;15815:44:2;;-1:-1:-1;;;15815:44:2;;15798:14;;-1:-1:-1;;;;;15815:29:2;;;;;:44;;15853:4;;15815:44;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;15798:61;-1:-1:-1;15877:11:2;15890:19;15798:61;15901:7;15890:10;:19::i;:::-;15869:41;;;;;;;15524:393;;;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:769:20:-;;127:3;120:4;112:6;108:17;104:27;94:2;;149:5;142;135:20;94:2;193:6;180:20;218:69;233:53;279:6;233:53;:::i;:::-;218:69;:::i;:::-;321:21;;;209:78;-1:-1:-1;361:4:20;381:14;;;;415:15;;;461;;;449:28;;445:37;;442:46;-1:-1:-1;439:2:20;;;501:1;498;491:12;439:2;523:1;533:244;547:6;544:1;541:13;533:244;;;622:3;609:17;639:33;666:5;639:33;:::i;:::-;685:18;;723:12;;;;755;;;;569:1;562:9;533:244;;;537:3;;;;;84:699;;;;:::o;788:766::-;;912:3;905:4;897:6;893:17;889:27;879:2;;934:5;927;920:20;879:2;971:6;965:13;996:69;1011:53;1057:6;1011:53;:::i;996:69::-;1099:21;;;987:78;-1:-1:-1;1139:4:20;1159:14;;;;1193:15;;;1239;;;1227:28;;1223:37;;1220:46;-1:-1:-1;1217:2:20;;;1279:1;1276;1269:12;1217:2;1301:1;1311:237;1325:6;1322:1;1319:13;1311:237;;;1393:3;1387:10;1410:33;1437:5;1410:33;:::i;:::-;1456:18;;1494:12;;;;1526;;;;1347:1;1340:9;1311:237;;1559:1109;;1670:3;1663:4;1655:6;1651:17;1647:27;1637:2;;1692:5;1685;1678:20;1637:2;1736:6;1723:20;1761:69;1776:53;1822:6;1776:53;:::i;1761:69::-;1864:21;;;1752:78;-1:-1:-1;1904:4:20;1924:14;;;;1958:15;;;1991:1;2001:661;2015:6;2012:1;2009:13;2001:661;;;2099:3;2086:17;2078:6;2074:30;2144:3;2139:2;2135;2131:11;2127:21;2117:2;;2162:1;2159;2152:12;2117:2;2216;2212;2208:11;2195:25;2248:55;2263:39;2293:8;2263:39;:::i;2248:55::-;2332:8;2323:7;2316:25;2364:2;2413:3;2408:2;2397:8;2393:2;2389:17;2385:26;2382:35;2379:2;;;2430:1;2427;2420:12;2379:2;2491:8;2486:2;2482;2478:11;2473:2;2464:7;2460:16;2447:53;-1:-1:-1;2553:1:20;2524:22;;;2520:31;;2513:42;;;;2568:20;;-1:-1:-1;2608:12:20;;;;2640;;;;2037:1;2030:9;2001:661;;2673:1053;;2795:3;2788:4;2780:6;2776:17;2772:27;2762:2;;2817:5;2810;2803:20;2762:2;2854:6;2848:13;2879:69;2894:53;2940:6;2894:53;:::i;2879:69::-;2982:21;;;2870:78;-1:-1:-1;3022:4:20;3042:14;;;;3076:15;;;3109:1;3119:601;3133:6;3130:1;3127:13;3119:601;;;3210:3;3204:10;3196:6;3192:23;3255:3;3250:2;3246;3242:11;3238:21;3228:2;;3273:1;3270;3263:12;3228:2;3320;3316;3312:11;3306:18;3352:55;3367:39;3397:8;3367:39;:::i;3352:55::-;3436:8;3427:7;3420:25;3468:2;3517:3;3512:2;3501:8;3497:2;3493:17;3489:26;3486:35;3483:2;;;3534:1;3531;3524:12;3483:2;3551:62;3604:8;3599:2;3590:7;3586:16;3581:2;3577;3573:11;3551:62;:::i;:::-;-1:-1:-1;3626:20:20;;-1:-1:-1;;3666:12:20;;;;3698;;;;3155:1;3148:9;3119:601;;3731:692;;3844:3;3837:4;3829:6;3825:17;3821:27;3811:2;;3866:5;3859;3852:20;3811:2;3910:6;3897:20;3935:69;3950:53;3996:6;3950:53;:::i;3935:69::-;4038:21;;;3926:78;-1:-1:-1;4078:4:20;4098:14;;;;4132:15;;;4178;;;4166:28;;4162:37;;4159:46;-1:-1:-1;4156:2:20;;;4218:1;4215;4208:12;4156:2;4240:1;4250:167;4264:6;4261:1;4258:13;4250:167;;;4325:17;;4313:30;;4363:12;;;;4395;;;;4286:1;4279:9;4250:167;;4428:689;;4552:3;4545:4;4537:6;4533:17;4529:27;4519:2;;4574:5;4567;4560:20;4519:2;4611:6;4605:13;4636:69;4651:53;4697:6;4651:53;:::i;4636:69::-;4739:21;;;4627:78;-1:-1:-1;4779:4:20;4799:14;;;;4833:15;;;4879;;;4867:28;;4863:37;;4860:46;-1:-1:-1;4857:2:20;;;4919:1;4916;4909:12;4857:2;4941:1;4951:160;4965:6;4962:1;4959:13;4951:160;;;5026:10;;5014:23;;5057:12;;;;5089;;;;4987:1;4980:9;4951:160;;5122:259;;5234:2;5222:9;5213:7;5209:23;5205:32;5202:2;;;5255:6;5247;5240:22;5202:2;5299:9;5286:23;5318:33;5345:5;5318:33;:::i;5386:263::-;;5509:2;5497:9;5488:7;5484:23;5480:32;5477:2;;;5530:6;5522;5515:22;5477:2;5567:9;5561:16;5586:33;5613:5;5586:33;:::i;5654:396::-;;;5780:2;5768:9;5759:7;5755:23;5751:32;5748:2;;;5801:6;5793;5786:22;5748:2;5845:9;5832:23;5864:33;5891:5;5864:33;:::i;:::-;5916:5;-1:-1:-1;5973:2:20;5958:18;;5945:32;5986;5945;5986;:::i;:::-;6037:7;6027:17;;;5738:312;;;;;:::o;6055:374::-;;6192:2;6180:9;6171:7;6167:23;6163:32;6160:2;;;6213:6;6205;6198:22;6160:2;6258:9;6245:23;6291:18;6283:6;6280:30;6277:2;;;6328:6;6320;6313:22;6277:2;6356:67;6415:7;6406:6;6395:9;6391:22;6356:67;:::i;:::-;6346:77;6150:279;-1:-1:-1;;;;6150:279:20:o;6434:1441::-;;;;;;;6765:3;6753:9;6744:7;6740:23;6736:33;6733:2;;;6787:6;6779;6772:22;6733:2;6832:9;6819:23;6861:18;6902:2;6894:6;6891:14;6888:2;;;6923:6;6915;6908:22;6888:2;6951:67;7010:7;7001:6;6990:9;6986:22;6951:67;:::i;:::-;6941:77;;7071:2;7060:9;7056:18;7043:32;7027:48;;7100:2;7090:8;7087:16;7084:2;;;7121:6;7113;7106:22;7084:2;7149:67;7208:7;7197:8;7186:9;7182:24;7149:67;:::i;:::-;7139:77;;7269:2;7258:9;7254:18;7241:32;7225:48;;7298:2;7288:8;7285:16;7282:2;;;7319:6;7311;7304:22;7282:2;7347:69;7408:7;7397:8;7386:9;7382:24;7347:69;:::i;:::-;7337:79;;7469:2;7458:9;7454:18;7441:32;7425:48;;7498:2;7488:8;7485:16;7482:2;;;7519:6;7511;7504:22;7482:2;7547:69;7608:7;7597:8;7586:9;7582:24;7547:69;:::i;:::-;7537:79;;7669:3;7658:9;7654:19;7641:33;7625:49;;7699:2;7689:8;7686:16;7683:2;;;7720:6;7712;7705:22;7683:2;;7748:69;7809:7;7798:8;7787:9;7783:24;7748:69;:::i;:::-;7738:79;;;7864:3;7853:9;7849:19;7836:33;7826:43;;6723:1152;;;;;;;;:::o;7880:656::-;;;8070:2;8058:9;8049:7;8045:23;8041:32;8038:2;;;8091:6;8083;8076:22;8038:2;8129:9;8123:16;8158:18;8199:2;8191:6;8188:14;8185:2;;;8220:6;8212;8205:22;8185:2;8248:78;8318:7;8309:6;8298:9;8294:22;8248:78;:::i;:::-;8238:88;;8372:2;8361:9;8357:18;8351:25;8335:41;;8401:2;8391:8;8388:16;8385:2;;;8422:6;8414;8407:22;8385:2;;8450:80;8522:7;8511:8;8500:9;8496:24;8450:80;:::i;8541:389::-;;8689:2;8677:9;8668:7;8664:23;8660:32;8657:2;;;8710:6;8702;8695:22;8657:2;8748:9;8742:16;8781:18;8773:6;8770:30;8767:2;;;8818:6;8810;8803:22;8767:2;8846:78;8916:7;8907:6;8896:9;8892:22;8846:78;:::i;8935:257::-;;9055:2;9043:9;9034:7;9030:23;9026:32;9023:2;;;9076:6;9068;9061:22;9023:2;9113:9;9107:16;9132:30;9156:5;9132:30;:::i;9197:1488::-;;9345:2;9333:9;9324:7;9320:23;9316:32;9313:2;;;9366:6;9358;9351:22;9313:2;9404:9;9398:16;9433:18;9474:2;9466:6;9463:14;9460:2;;;9495:6;9487;9480:22;9460:2;9523:22;;;;9579:4;9561:16;;;9557:27;9554:2;;;9602:6;9594;9587:22;9554:2;9633:20;9648:4;9633:20;:::i;:::-;9684:2;9678:9;9712:2;9702:8;9699:16;9696:2;;;9733:6;9725;9718:22;9696:2;9765:73;9830:7;9819:8;9815:2;9811:17;9765:73;:::i;:::-;9758:5;9751:88;;9878:2;9874;9870:11;9864:18;9907:2;9897:8;9894:16;9891:2;;;9928:6;9920;9913:22;9891:2;9969:71;10032:7;10021:8;10017:2;10013:17;9969:71;:::i;:::-;9964:2;9957:5;9953:14;9946:95;;10080:2;10076;10072:11;10066:18;10109:2;10099:8;10096:16;10093:2;;;10130:6;10122;10115:22;10093:2;10171:73;10236:7;10225:8;10221:2;10217:17;10171:73;:::i;:::-;10166:2;10159:5;10155:14;10148:97;;10284:2;10280;10276:11;10270:18;10313:2;10303:8;10300:16;10297:2;;;10334:6;10326;10319:22;10297:2;10375:73;10440:7;10429:8;10425:2;10421:17;10375:73;:::i;:::-;10370:2;10363:5;10359:14;10352:97;;10488:3;10484:2;10480:12;10474:19;10518:2;10508:8;10505:16;10502:2;;;10539:6;10531;10524:22;10502:2;10581:73;10646:7;10635:8;10631:2;10627:17;10581:73;:::i;:::-;10575:3;10564:15;;10557:98;-1:-1:-1;10568:5:20;9303:1382;-1:-1:-1;;;;;9303:1382:20:o;10690:190::-;;10802:2;10790:9;10781:7;10777:23;10773:32;10770:2;;;10823:6;10815;10808:22;10770:2;-1:-1:-1;10851:23:20;;10760:120;-1:-1:-1;10760:120:20:o;10885:194::-;;11008:2;10996:9;10987:7;10983:23;10979:32;10976:2;;;11029:6;11021;11014:22;10976:2;-1:-1:-1;11057:16:20;;10966:113;-1:-1:-1;10966:113:20:o;11084:469::-;;11181:5;11175:12;11208:6;11203:3;11196:19;11234:4;11263:2;11258:3;11254:12;11247:19;;11300:2;11293:5;11289:14;11321:3;11333:195;11347:6;11344:1;11341:13;11333:195;;;11412:13;;-1:-1:-1;;;;;11408:39:20;11396:52;;11468:12;;;;11503:15;;;;11444:1;11362:9;11333:195;;;-1:-1:-1;11544:3:20;;11151:402;-1:-1:-1;;;;;11151:402:20:o;11558:443::-;;11655:5;11649:12;11682:6;11677:3;11670:19;11708:4;11737:2;11732:3;11728:12;11721:19;;11774:2;11767:5;11763:14;11795:3;11807:169;11821:6;11818:1;11815:13;11807:169;;;11882:13;;11870:26;;11916:12;;;;11951:15;;;;11843:1;11836:9;11807:169;;12006:259;;12087:5;12081:12;12114:6;12109:3;12102:19;12130:63;12186:6;12179:4;12174:3;12170:14;12163:4;12156:5;12152:16;12130:63;:::i;:::-;12247:2;12226:15;-1:-1:-1;;12222:29:20;12213:39;;;;12254:4;12209:50;;12057:208;-1:-1:-1;;12057:208:20:o;12270:274::-;;12437:6;12431:13;12453:53;12499:6;12494:3;12487:4;12479:6;12475:17;12453:53;:::i;:::-;12522:16;;;;;12407:137;-1:-1:-1;;12407:137:20:o;12549:205::-;12749:3;12740:14::o;12759:203::-;-1:-1:-1;;;;;12923:32:20;;;;12905:51;;12893:2;12878:18;;12860:102::o;13183:282::-;-1:-1:-1;;;;;13383:32:20;;;;13365:51;;13447:2;13432:18;;13425:34;13353:2;13338:18;;13320:145::o;13470:304::-;-1:-1:-1;;;;;13700:15:20;;;13682:34;;13752:15;;13747:2;13732:18;;13725:43;13632:2;13617:18;;13599:175::o;13779:375::-;-1:-1:-1;;;;;14037:15:20;;;14019:34;;14089:15;;;;14084:2;14069:18;;14062:43;14136:2;14121:18;;14114:34;;;;13969:2;13954:18;;13936:218::o;14438:267::-;;14617:2;14606:9;14599:21;14637:62;14695:2;14684:9;14680:18;14672:6;14637:62;:::i;14710:267::-;;14889:2;14878:9;14871:21;14909:62;14967:2;14956:9;14952:18;14944:6;14909:62;:::i;14982:187::-;15147:14;;15140:22;15122:41;;15110:2;15095:18;;15077:92::o;15174:221::-;;15323:2;15312:9;15305:21;15343:46;15385:2;15374:9;15370:18;15362:6;15343:46;:::i;15400:335::-;15602:2;15584:21;;;15641:2;15621:18;;;15614:30;-1:-1:-1;;;15675:2:20;15660:18;;15653:41;15726:2;15711:18;;15574:161::o;15740:328::-;15942:2;15924:21;;;15981:1;15961:18;;;15954:29;-1:-1:-1;;;16014:2:20;15999:18;;15992:35;16059:2;16044:18;;15914:154::o;16073:334::-;16275:2;16257:21;;;16314:2;16294:18;;;16287:30;-1:-1:-1;;;16348:2:20;16333:18;;16326:40;16398:2;16383:18;;16247:160::o;16412:351::-;16614:2;16596:21;;;16653:2;16633:18;;;16626:30;16692:29;16687:2;16672:18;;16665:57;16754:2;16739:18;;16586:177::o;16768:337::-;16970:2;16952:21;;;17009:2;16989:18;;;16982:30;-1:-1:-1;;;17043:2:20;17028:18;;17021:43;17096:2;17081:18;;16942:163::o;17110:354::-;17312:2;17294:21;;;17351:2;17331:18;;;17324:30;17390:32;17385:2;17370:18;;17363:60;17455:2;17440:18;;17284:180::o;17469:402::-;17671:2;17653:21;;;17710:2;17690:18;;;17683:30;17749:34;17744:2;17729:18;;17722:62;-1:-1:-1;;;17815:2:20;17800:18;;17793:36;17861:3;17846:19;;17643:228::o;17876:328::-;18078:2;18060:21;;;18117:1;18097:18;;;18090:29;-1:-1:-1;;;18150:2:20;18135:18;;18128:35;18195:2;18180:18;;18050:154::o;18209:338::-;18411:2;18393:21;;;18450:2;18430:18;;;18423:30;-1:-1:-1;;;18484:2:20;18469:18;;18462:44;18538:2;18523:18;;18383:164::o;18552:342::-;18754:2;18736:21;;;18793:2;18773:18;;;18766:30;-1:-1:-1;;;18827:2:20;18812:18;;18805:48;18885:2;18870:18;;18726:168::o;18899:339::-;19101:2;19083:21;;;19140:2;19120:18;;;19113:30;-1:-1:-1;;;19174:2:20;19159:18;;19152:45;19229:2;19214:18;;19073:165::o;19243:327::-;19445:2;19427:21;;;19484:1;19464:18;;;19457:29;-1:-1:-1;;;19517:2:20;19502:18;;19495:34;19561:2;19546:18;;19417:153::o;19575:353::-;19777:2;19759:21;;;19816:2;19796:18;;;19789:30;19855:31;19850:2;19835:18;;19828:59;19919:2;19904:18;;19749:179::o;19933:335::-;20135:2;20117:21;;;20174:2;20154:18;;;20147:30;-1:-1:-1;;;20208:2:20;20193:18;;20186:41;20259:2;20244:18;;20107:161::o;20273:330::-;20475:2;20457:21;;;20514:1;20494:18;;;20487:29;-1:-1:-1;;;20547:2:20;20532:18;;20525:37;20594:2;20579:18;;20447:156::o;20608:406::-;20810:2;20792:21;;;20849:2;20829:18;;;20822:30;20888:34;20883:2;20868:18;;20861:62;-1:-1:-1;;;20954:2:20;20939:18;;20932:40;21004:3;20989:19;;20782:232::o;21019:418::-;21221:2;21203:21;;;21260:2;21240:18;;;21233:30;21299:34;21294:2;21279:18;;21272:62;-1:-1:-1;;;21365:2:20;21350:18;;21343:52;21427:3;21412:19;;21193:244::o;21442:1652::-;;21613:2;21642;21631:9;21624:21;21680:6;21674:13;21723:4;21718:2;21707:9;21703:18;21696:32;21751:69;21815:3;21804:9;21800:19;21786:12;21751:69;:::i;:::-;21857:15;;;21851:22;-1:-1:-1;;21939:22:20;;;21935:31;;21930:2;21915:18;;21908:59;22016:21;;22046:22;;;21939;;-1:-1:-1;22182:23:20;;;;22084:15;;;;22138;;;22126:28;;22122:37;;22223:4;22236:248;22250:6;22247:1;22244:13;22236:248;;;22336:2;22327:6;22319;22315:19;22311:28;22306:3;22299:41;22363;22397:6;22388;22382:13;22363:41;:::i;:::-;22427:15;;;;22462:12;;;;22353:51;-1:-1:-1;22272:1:20;22265:9;22236:248;;;22240:3;22533:2;22525:6;22521:15;22515:22;22493:44;;22601:2;22589:9;22581:6;22577:22;22573:31;22568:2;22557:9;22553:18;22546:59;22628:58;22679:6;22663:14;22628:58;:::i;:::-;22614:72;;;;;22735:2;22727:6;22723:15;22717:22;22695:44;;22804:2;22792:9;22784:6;22780:22;22776:31;22770:3;22759:9;22755:19;22748:60;22831:58;22882:6;22866:14;22831:58;:::i;:::-;22817:72;;22938:3;22930:6;22926:16;22920:23;22898:45;;23009:2;22997:9;22989:6;22985:22;22981:31;22974:4;22963:9;22959:20;22952:61;;;23030:58;23081:6;23065:14;23030:58;:::i;:::-;23022:66;21593:1501;-1:-1:-1;;;;;21593:1501:20:o;23099:177::-;23245:25;;;23233:2;23218:18;;23200:76::o;23281:588::-;;23580:6;23569:9;23562:25;23623:6;23618:2;23607:9;23603:18;23596:34;23666:3;23661:2;23650:9;23646:18;23639:31;23687:63;23745:3;23734:9;23730:19;23722:6;23687:63;:::i;:::-;-1:-1:-1;;;;;23786:32:20;;;;23781:2;23766:18;;23759:60;-1:-1:-1;23850:3:20;23835:19;23828:35;23679:71;23552:317;-1:-1:-1;;;23552:317:20:o;23874:350::-;24091:25;;;24163:2;24152:22;;;;24147:2;24132:18;;24125:50;24206:2;24191:18;;24184:34;24079:2;24064:18;;24046:178::o;24229:242::-;24299:2;24293:9;24329:17;;;24376:18;24361:34;;24397:22;;;24358:62;24355:2;;;24423:9;24355:2;24450;24443:22;24273:198;;-1:-1:-1;24273:198:20:o;24476:183::-;;24575:18;24567:6;24564:30;24561:2;;;24597:9;24561:2;-1:-1:-1;24648:4:20;24629:17;;;24625:28;;24551:108::o;24664:181::-;;24747:18;24739:6;24736:30;24733:2;;;24769:9;24733:2;-1:-1:-1;24828:2:20;24805:17;-1:-1:-1;;24801:31:20;24834:4;24797:42;;24723:122::o;24850:258::-;24922:1;24932:113;24946:6;24943:1;24940:13;24932:113;;;25022:11;;;25016:18;25003:11;;;24996:39;24968:2;24961:10;24932:113;;;25063:6;25060:1;25057:13;25054:2;;;-1:-1:-1;;25098:1:20;25080:16;;25073:27;24903:205::o;25113:133::-;-1:-1:-1;;;;;25190:31:20;;25180:42;;25170:2;;25236:1;25233;25226:12;25251:120;25339:5;25332:13;25325:21;25318:5;25315:32;25305:2;;25361:1;25358;25351:12

Swarm Source

ipfs://2b1c2a16b490a272394d6728ea3eeba1c311f65b6bcfce87bc61bfce987b34b2

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  ]
[ 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.