ETH Price: $3,459.03 (-0.70%)
Gas: 3 Gwei

Contract

0xc02e10157c71008B6b8F8E6AbF8d3EaC60ed561e
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
0x60806040149734962022-06-16 13:18:13746 days ago1655385493IN
 Create: TheVault
0 ETH0.1828513345.67316715

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
TheVault

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license
File 1 of 16 : TheVault.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

import {Vault} from "Vault.sol";

contract TheVault is Vault {
    // So Brownie compiles it tbh
    // Changes here invalidate the bytecode, breaking trust of the mix
    // DO NOT CHANGE THIS FILE
}

File 2 of 16 : Vault.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.6.12;

import "IERC20Upgradeable.sol";
import "SafeMathUpgradeable.sol";
import "AddressUpgradeable.sol";
import "SafeERC20Upgradeable.sol";
import "ERC20Upgradeable.sol";
import "PausableUpgradeable.sol";
import "ReentrancyGuardUpgradeable.sol";

import "SettAccessControl.sol";

import {IVault} from "IVault.sol";
import {IStrategy} from "IStrategy.sol";
import {IERC20Detailed} from "IERC20Detailed.sol";
import {BadgerGuestListAPI} from "BadgerGuestlistApi.sol";

/*
    Source: https://github.com/iearn-finance/yearn-protocol/blob/develop/contracts/vaults/yVault.sol
    
    Changelog:

    V1.1
    * Strategist no longer has special function calling permissions
    * Version function added to contract
    * All write functions, with the exception of transfer, are pausable
    * Keeper or governance can pause
    * Only governance can unpause

    V1.2
    * Transfer functions are now pausable along with all other non-permissioned write functions
    * All permissioned write functions, with the exception of pause() & unpause(), are pausable as well

    V1.3
    * Add guest list functionality
    * All deposits can be optionally gated by external guestList approval logic on set guestList contract

    V1.4
    * Add depositFor() to deposit on the half of other users. That user will then be blockLocked.

    V1.5
    * Removed Controller
        - Removed harvest from vault (only on strategy)
    * Params added to track autocompounded rewards (lifeTimeEarned, lastHarvestedAt, lastHarvestAmount, assetsAtLastHarvest)
      this would work in sync with autoCompoundRatio to help us track harvests better.
    * Fees
        - Strategy would report the autocompounded harvest amount to the vault
        - Calculation performanceFeeGovernance, performanceFeeStrategist, withdrawalFee, managementFee moved to the vault.
        - Vault mints shares for performanceFees and managementFee to the respective recipient (treasury, strategist)
        - withdrawal fees is transferred to the rewards address set
    * Permission:
        - Strategist can now set performance, withdrawal and management fees
        - Governance will determine maxPerformanceFee, maxWithdrawalFee, maxManagementFee that can be set to prevent rug of funds.
    * Strategy would take the actors from the vault it is connected to
    * All governance related fees goes to treasury
*/

contract Vault is ERC20Upgradeable, SettAccessControl, PausableUpgradeable, ReentrancyGuardUpgradeable {
    using SafeERC20Upgradeable for IERC20Upgradeable;
    using AddressUpgradeable for address;
    using SafeMathUpgradeable for uint256;

    uint256 constant ONE_ETH = 1e18;

    /// ===== Storage Variables ====

    IERC20Upgradeable public token; // Token used for deposits
    BadgerGuestListAPI public guestList; // guestlist when vault is in experiment/ guarded state

    bool public pausedDeposit; // false by default Allows to only block deposits, use pause for the normal pause state

    address public strategy; // address of the strategy connected to the vault
    address public guardian; // guardian of vault and strategy
    address public treasury; // set by governance ... any fees go there

    address public badgerTree; // Address we send tokens too via reportAdditionalTokens

    /// @dev name and symbol prefixes for lpcomponent token of vault
    string internal constant _defaultNamePrefix = "Badger Sett ";
    string internal constant _symbolSymbolPrefix = "b";

    /// Params to track autocompounded rewards
    uint256 public lifeTimeEarned; // keeps track of total earnings
    uint256 public lastHarvestedAt; // timestamp of the last harvest
    uint256 public lastHarvestAmount; // amount harvested during last harvest
    uint256 public assetsAtLastHarvest; // assets for which the harvest took place.

    mapping (address => uint256) public additionalTokensEarned;
    mapping (address => uint256) public lastAdditionalTokenAmount;

    /// Fees ///
    /// @notice all fees will be in bps
    uint256 public performanceFeeGovernance; // Perf fee sent to `treasury`
    uint256 public performanceFeeStrategist; // Perf fee sent to `strategist`
    uint256 public withdrawalFee; // fee issued to `treasury` on withdrawal 
    uint256 public managementFee; // fee issued to `treasury` on report (typically on harvest, but only if strat is autocompounding)

    uint256 public maxPerformanceFee; // maximum allowed performance fees
    uint256 public maxWithdrawalFee; // maximum allowed withdrawal fees
    uint256 public maxManagementFee; // maximum allowed management fees

    uint256 public toEarnBps; // NOTE: in BPS, minimum amount of token to deposit into strategy when earn is called

    /// ===== Constants ====

    uint256 public constant MAX_BPS = 10_000;
    uint256 public constant SECS_PER_YEAR = 31_556_952; // 365.2425 days

    uint256 public constant WITHDRAWAL_FEE_HARD_CAP = 200; // Never higher than 2%
    uint256 public constant PERFORMANCE_FEE_HARD_CAP = 3_000; // Never higher than 30% // 30% maximum performance fee // We usually do 20, so this is insanely high already
    uint256 public constant MANAGEMENT_FEE_HARD_CAP = 200; // Never higher than 2%

    /// ===== Events ====

    // Emitted when a token is sent to the badgerTree for emissions
    event TreeDistribution(
        address indexed token,
        uint256 amount,
        uint256 indexed blockNumber,
        uint256 timestamp
    );

    // Emitted during a report, when there has been an increase in pricePerFullShare (ppfs)
    event Harvested(address indexed token, uint256 amount, uint256 indexed blockNumber, uint256 timestamp);

    event SetTreasury(address indexed newTreasury);
    event SetStrategy(address indexed newStrategy);
    event SetToEarnBps(uint256 newEarnToBps);
    event SetMaxWithdrawalFee(uint256 newMaxWithdrawalFee);
    event SetMaxPerformanceFee(uint256 newMaxPerformanceFee);
    event SetMaxManagementFee(uint256 newMaxManagementFee);
    event SetGuardian(address indexed newGuardian);
    event SetGuestList(address indexed newGuestList);
    event SetWithdrawalFee(uint256 newWithdrawalFee);
    event SetPerformanceFeeStrategist(uint256 newPerformanceFeeStrategist);
    event SetPerformanceFeeGovernance(uint256 newPerformanceFeeGovernance);
    event SetManagementFee(uint256 newManagementFee);

    event PauseDeposits(address indexed pausedBy);
    event UnpauseDeposits(address indexed pausedBy);

    /// @notice Initializes the Sett. Can only be called once, ideally when the contract is deployed.
    /// @param _token Address of the token that can be deposited into the sett.
    /// @param _governance Address authorized as governance.
    /// @param _keeper Address authorized as keeper.
    /// @param _guardian Address authorized as guardian.
    /// @param _treasury Address to distribute governance fees/rewards to.
    /// @param _strategist Address authorized as strategist.
    /// @param _badgerTree Address of badgerTree used for emissions.
    /// @param _name Specify a custom sett name. Leave empty for default value.
    /// @param _symbol Specify a custom sett symbol. Leave empty for default value.
    /// @param _feeConfig Values for the 4 different types of fees charges by the sett
    ///         [performanceFeeGovernance, performanceFeeStrategist, withdrawToVault, managementFee]
    ///         Each fee should be less than the constant hard-caps defined above. 
    function initialize(
        address _token,
        address _governance,
        address _keeper,
        address _guardian,
        address _treasury,
        address _strategist,
        address _badgerTree,
        string memory _name,
        string memory _symbol,
        uint256[4] memory _feeConfig
    ) public initializer whenNotPaused {
        require(_token != address(0)); // dev: _token address should not be zero
        require(_governance != address(0)); // dev: _governance address should not be zero
        require(_keeper != address(0)); // dev: _keeper address should not be zero
        require(_guardian != address(0)); // dev: _guardian address should not be zero
        require(_treasury != address(0)); // dev: _treasury address should not be zero
        require(_strategist != address(0)); // dev: _strategist address should not be zero
        require(_badgerTree != address(0)); // dev: _badgerTree address should not be zero

        // Check for fees being reasonable (see below for interpretation)
        require(_feeConfig[0] <= PERFORMANCE_FEE_HARD_CAP, "performanceFeeGovernance too high");
        require(_feeConfig[1] <= PERFORMANCE_FEE_HARD_CAP, "performanceFeeStrategist too high");
        require(_feeConfig[2] <= WITHDRAWAL_FEE_HARD_CAP, "withdrawalFee too high");
        require(_feeConfig[3] <= MANAGEMENT_FEE_HARD_CAP, "managementFee too high");

        string memory name;
        string memory symbol;


        // If they are non empty string we'll use the custom names
        // Else just add the default prefix
        IERC20Detailed namedToken = IERC20Detailed(_token);

        if(keccak256(abi.encodePacked(_name)) != keccak256("")) {
            name = _name;
        } else {
            name = string(abi.encodePacked(_defaultNamePrefix, namedToken.name()));
        }

        if (keccak256(abi.encodePacked(_symbol)) != keccak256("")) {
            symbol = _symbol;
        } else {
            symbol = string(abi.encodePacked(_symbolSymbolPrefix, namedToken.symbol()));
        }

        // Initializing the lpcomponent token
        __ERC20_init(name, symbol);
        // Initialize the other contracts
        __Pausable_init();
        __ReentrancyGuard_init();

        token = IERC20Upgradeable(_token);
        governance = _governance;
        treasury = _treasury;
        strategist = _strategist;
        keeper = _keeper;
        guardian = _guardian;
        badgerTree = _badgerTree;

        lastHarvestedAt = block.timestamp; // setting initial value to the time when the vault was deployed

        performanceFeeGovernance = _feeConfig[0];
        performanceFeeStrategist = _feeConfig[1];
        withdrawalFee = _feeConfig[2];
        managementFee = _feeConfig[3];
        maxPerformanceFee = PERFORMANCE_FEE_HARD_CAP; // 30% max performance fee
        maxWithdrawalFee = WITHDRAWAL_FEE_HARD_CAP; // 2% maximum withdrawal fee
        maxManagementFee = MANAGEMENT_FEE_HARD_CAP; // 2% maximum management fee

        toEarnBps = 9_500; // initial value of toEarnBps // 95% is invested to the strategy, 5% for cheap withdrawals
    }

    /// ===== Modifiers ====

    /// @notice Checks whether a call is from guardian or governance. 
    function _onlyAuthorizedPausers() internal view {
        require(msg.sender == guardian || msg.sender == governance, "onlyPausers");
    }

    /// @notice Checks whether a call is from the strategy.
    function _onlyStrategy() internal view {
        require(msg.sender == strategy, "onlyStrategy");
    }

    /// ===== View Functions =====
    
    /// @notice Used to track the deployed version of the contract.
    /// @return Current version of the contract.
    function version() external pure returns (string memory) {
        return "1.5";
    }

    /// @notice Gives the price for a single Sett share.
    /// @dev Sett starts with a price per share of 1.
    /// @return Value of a single share.
    function getPricePerFullShare() public view returns (uint256) {
        if (totalSupply() == 0) {
            return ONE_ETH;
        }
        return balance().mul(ONE_ETH).div(totalSupply());
    }

    /// @notice Gives the total balance of the underlying token within the sett and strategy system.
    /// @return Balance of token handled by the sett.
    function balance() public view returns (uint256) {
        return token.balanceOf(address(this)).add(IStrategy(strategy).balanceOf());
    }

    /// @notice Defines how much of the Setts' underlying is available for strategy to borrow.
    /// @return Amount of tokens that the sett can provide to the strategy.
    function available() public view returns (uint256) {
        return token.balanceOf(address(this)).mul(toEarnBps).div(MAX_BPS);
    }

    /// ===== Public Actions =====

    /// @notice Deposits `_amount` tokens, issuing shares. 
    ///         Note that deposits are not accepted when the Sett is paused or when `pausedDeposit` is true. 
    /// @dev See `_depositFor` for details on how deposit is implemented. 
    /// @param _amount Quantity of tokens to deposit. 
    function deposit(uint256 _amount) external whenNotPaused {
        _depositWithAuthorization(_amount, new bytes32[](0));
    }

    /// @notice Deposits `_amount` tokens, issuing shares. 
    ///         Checks the guestlist to verify that the calling account is authorized to make a deposit for the specified `_amount`.
    ///         Note that deposits are not accepted when the Sett is paused or when `pausedDeposit` is true. 
    /// @dev See `_depositForWithAuthorization` for details on guestlist authorization.
    /// @param _amount Quantity of tokens to deposit. 
    /// @param proof Merkle proof to validate in the guestlist.
    function deposit(uint256 _amount, bytes32[] memory proof) external whenNotPaused {
        _depositWithAuthorization(_amount, proof);
    }

    /// @notice Deposits all tokens, issuing shares. 
    ///         Note that deposits are not accepted when the Sett is paused or when `pausedDeposit` is true. 
    /// @dev See `_depositFor` for details on how deposit is implemented. 
    function depositAll() external whenNotPaused {
        _depositWithAuthorization(token.balanceOf(msg.sender), new bytes32[](0));
    }

    /// @notice Deposits all tokens, issuing shares. 
    ///         Checks the guestlist to verify that the calling is authorized to make a full deposit.
    ///         Note that deposits are not accepted when the Sett is paused or when `pausedDeposit` is true. 
    /// @dev See `_depositForWithAuthorization` for details on guestlist authorization.
    /// @param proof Merkle proof to validate in the guestlist.
    function depositAll(bytes32[] memory proof) external whenNotPaused {
        _depositWithAuthorization(token.balanceOf(msg.sender), proof);
    }

    /// @notice Deposits `_amount` tokens, issuing shares to `recipient`. 
    ///         Note that deposits are not accepted when the Sett is paused or when `pausedDeposit` is true. 
    /// @dev See `_depositFor` for details on how deposit is implemented. 
    /// @param _recipient Address to issue the Sett shares to.
    /// @param _amount Quantity of tokens to deposit. 
    function depositFor(address _recipient, uint256 _amount) external whenNotPaused {
        _depositForWithAuthorization(_recipient, _amount, new bytes32[](0));
    }

    /// @notice Deposits `_amount` tokens, issuing shares to `recipient`. 
    ///         Checks the guestlist to verify that `recipient` is authorized to make a deposit for the specified `_amount`.
    ///         Note that deposits are not accepted when the Sett is paused or when `pausedDeposit` is true. 
    /// @dev See `_depositForWithAuthorization` for details on guestlist authorization.
    /// @param _recipient Address to issue the Sett shares to.
    /// @param _amount Quantity of tokens to deposit. 
    function depositFor(
        address _recipient,
        uint256 _amount,
        bytes32[] memory proof
    ) external whenNotPaused {
        _depositForWithAuthorization(_recipient, _amount, proof);
    }

    /// @notice Redeems `_shares` for an appropriate amount of tokens.
    ///         Note that withdrawals are not processed when the Sett is paused. 
    /// @dev See `_withdraw` for details on how withdrawals are processed.
    /// @param _shares Quantity of shares to redeem. 
    function withdraw(uint256 _shares) external whenNotPaused {
        _withdraw(_shares);
    }

    /// @notice Redeems all shares, issuing an appropriate amount of tokens. 
    ///         Note that withdrawals are not processed when the Sett is paused. 
    /// @dev See `_withdraw` for details on how withdrawals are processed.
    function withdrawAll() external whenNotPaused {
        _withdraw(balanceOf(msg.sender));
    }

    /// ===== Permissioned Actions: Strategy =====

    /// @notice Used by the strategy to report a harvest to the sett.
    ///         Issues shares for the strategist and treasury based on the performance fees and harvested amount. 
    ///         Issues shares for the treasury based on the management fee and the time elapsed since last harvest. 
    ///         Updates harvest variables for on-chain APR tracking.
    ///         This can only be called by the strategy.
    /// @dev This implicitly trusts that the strategy reports the correct amount.
    ///      Pausing on this function happens at the strategy level.
    /// @param _harvestedAmount Amount of underlying token harvested by the strategy.
    function reportHarvest(
        uint256 _harvestedAmount
    ) external nonReentrant {
        _onlyStrategy();

        uint256 harvestTime = block.timestamp;
        uint256 assetsAtHarvest = balance().sub(_harvestedAmount); // Must be less than or equal or revert

        _handleFees(_harvestedAmount, harvestTime);

        // Updated lastHarvestAmount
        lastHarvestAmount = _harvestedAmount;

        // if we withdrawAll
        // we will have some yield left
        // having 0 for assets will inflate APY
        // Instead, have the last harvest report with the previous assets
        // And if you end up harvesting again, that report will have both 0s
        if (assetsAtHarvest != 0) {
            assetsAtLastHarvest = assetsAtHarvest;
        } else if (_harvestedAmount == 0) {
            // If zero
            assetsAtLastHarvest = 0;
        }

        lifeTimeEarned = lifeTimeEarned.add(_harvestedAmount);
        // Update time either way
        lastHarvestedAt = harvestTime;

        emit Harvested(address(token), _harvestedAmount, block.number, block.timestamp);
    }

    /// @notice Used by the strategy to report harvest of additional tokens to the sett.
    ///         Charges performance fees on the additional tokens and transfers fees to treasury and strategist. 
    ///         The remaining amount is sent to badgerTree for emissions.
    ///         Updates harvest variables for on-chain APR tracking.
    ///         This can only be called by the strategy.
    /// @dev This function is called after the strategy sends the additional tokens to the sett.
    ///      Pausing on this function happens at the strategy level.
    /// @param _token Address of additional token harvested by the strategy.
    function reportAdditionalToken(address _token) external nonReentrant {
        _onlyStrategy();
        require(address(token) != _token, "No want");
        uint256 tokenBalance = IERC20Upgradeable(_token).balanceOf(address(this));

        additionalTokensEarned[_token] = additionalTokensEarned[_token].add(tokenBalance);
        lastAdditionalTokenAmount[_token] = tokenBalance;

        // We may have more, but we still report only what the strat sent
        uint256 governanceRewardsFee = _calculateFee(tokenBalance, performanceFeeGovernance);
        uint256 strategistRewardsFee = _calculateFee(tokenBalance, performanceFeeStrategist);

        if(governanceRewardsFee != 0) {
            IERC20Upgradeable(_token).safeTransfer(treasury, governanceRewardsFee);

        }

        if(strategistRewardsFee != 0) {
            IERC20Upgradeable(_token).safeTransfer(strategist, strategistRewardsFee);
        }

        // Send rest to tree
        uint256 newBalance = IERC20Upgradeable(_token).balanceOf(address(this));
        IERC20Upgradeable(_token).safeTransfer(badgerTree, newBalance);
        emit TreeDistribution(_token, newBalance, block.number, block.timestamp);
    }

    /// ===== Permissioned Actions: Governance =====

    /// @notice Changes the treasury address.
    ///         Treasury is recipient of management and governance performance fees.
    ///         This can only be called by governance.
    ///         Note that this can only be called when sett is not paused.
    /// @param _treasury Address of the new treasury.
    function setTreasury(address _treasury) external whenNotPaused {
        _onlyGovernance();
        require(_treasury != address(0), "Address 0");

        treasury = _treasury;
        emit SetTreasury(_treasury);
    }

    /// @notice Changes the strategy address.
    ///         This can only be called by governance.
    ///         Note that this can only be called when sett is not paused.
    /// @dev This is a rug vector, pay extremely close attention to the next strategy being set.
    ///      Changing the strategy should happen only via timelock.
    ///      This function must not be callable when the sett is paused as this would force depositors into a strategy they may not want to use.
    /// @param _strategy Address of new strategy.
    function setStrategy(address _strategy) external whenNotPaused {
        _onlyGovernance();
        require(_strategy != address(0), "Address 0");


        /// NOTE: Migrate funds if settings strategy when already existing one
        if (strategy != address(0)) {
            require(IStrategy(strategy).balanceOf() == 0, "Please withdrawToVault before changing strat");
        }
        strategy = _strategy;
        emit SetStrategy(_strategy);
    }

    // === Setters that can be called by governance even when paused ===

    /// @notice Sets the max withdrawal fee that can be charged by the Sett.
    ///         This can only be called by governance.
    /// @dev The input `_fees` should be less than the `WITHDRAWAL_FEE_HARD_CAP` hard-cap.
    /// @param _fees The new maximum cap for withdrawal fee.
    function setMaxWithdrawalFee(uint256 _fees) external {
        _onlyGovernance();
        require(_fees <= WITHDRAWAL_FEE_HARD_CAP, "withdrawalFee too high");

        maxWithdrawalFee = _fees;
        emit SetMaxWithdrawalFee(_fees);
    }

    /// @notice Sets the max performance fee that can be charged by the Sett.
    ///         This can only be called by governance.
    /// @dev The input `_fees` should be less than the `PERFORMANCE_FEE_HARD_CAP` hard-cap.
    /// @param _fees The new maximum cap for performance fee.
    function setMaxPerformanceFee(uint256 _fees) external {
        _onlyGovernance();
        require(_fees <= PERFORMANCE_FEE_HARD_CAP, "performanceFeeStrategist too high");

        maxPerformanceFee = _fees;
        emit SetMaxPerformanceFee(_fees);
    }

    /// @notice Sets the max management fee that can be charged by the Sett.
    ///         This can only be called by governance.
    /// @dev The input `_fees` should be less than the `MANAGEMENT_FEE_HARD_CAP` hard-cap.
    /// @param _fees The new maximum cap for management fee.
    function setMaxManagementFee(uint256 _fees) external {
        _onlyGovernance();
        require(_fees <= MANAGEMENT_FEE_HARD_CAP, "managementFee too high");

        maxManagementFee = _fees;
        emit SetMaxManagementFee(_fees);
    }

    /// @notice Changes the guardian address.
    ///         Guardian is an authorized actor that can pause the sett in case of an emergency.
    ///         This can only be called by governance.
    /// @param _guardian Address of the new guardian.
    function setGuardian(address _guardian) external {
        _onlyGovernance();
        require(_guardian != address(0), "Address cannot be 0x0");

        guardian = _guardian;
        emit SetGuardian(_guardian);
    }

    /// ===== Permissioned Functions: Trusted Actors =====

    /// @notice Sets the fraction of sett balance (in basis points) that the strategy can borrow.
    ///         This can be called by either governance or strategist.
    ///         Note that this can only be called when the sett is not paused.
    /// @param _newToEarnBps The new maximum cap for management fee.
    function setToEarnBps(uint256 _newToEarnBps) external whenNotPaused {
        _onlyGovernanceOrStrategist();
        require(_newToEarnBps <= MAX_BPS, "toEarnBps should be <= MAX_BPS");

        toEarnBps = _newToEarnBps;
        emit SetToEarnBps(_newToEarnBps);
    } 

    /// @notice Changes the guestlist address.
    ///         The guestList is used to gate or limit deposits. If no guestlist is set then anyone can deposit any amount.
    ///         This can be called by either governance or strategist.
    ///         Note that this can only be called when the sett is not paused.
    /// @param _guestList Address of the new guestlist.
    function setGuestList(address _guestList) external whenNotPaused {
        _onlyGovernanceOrStrategist();
        guestList = BadgerGuestListAPI(_guestList);
        emit SetGuestList(_guestList);
    }

    /// @notice Sets the withdrawal fee charged by the Sett.
    ///         The fee is taken at the time of withdrawals in the underlying token which is then used to issue new shares for the treasury.
    ///         The new withdrawal fee should be less than `maxWithdrawalFee`.
    ///         This can be called by either governance or strategist.
    /// @dev See `_withdraw` to see how withdrawal fee is charged.
    /// @param _withdrawalFee The new withdrawal fee.
    function setWithdrawalFee(uint256 _withdrawalFee) external whenNotPaused {
        _onlyGovernanceOrStrategist();
        require(_withdrawalFee <= maxWithdrawalFee, "Excessive withdrawal fee");
        withdrawalFee = _withdrawalFee;
        emit SetWithdrawalFee(_withdrawalFee);
    }

    /// @notice Sets the performance fee taken by the strategist on the harvests.
    ///         The fee is taken at the time of harvest reporting for both the underlying token and additional tokens.
    ///         For the underlying token, the fee is used to issue new shares for the strategist.
    ///         The new performance fee should be less than `maxPerformanceFee`.
    ///         This can be called by either governance or strategist.
    /// @dev See `reportHarvest` and `reportAdditionalToken` to see how performance fees are charged.
    /// @param _performanceFeeStrategist The new performance fee.
    function setPerformanceFeeStrategist(uint256 _performanceFeeStrategist) external whenNotPaused {
        _onlyGovernanceOrStrategist();
        require(_performanceFeeStrategist <= maxPerformanceFee, "Excessive strategist performance fee");
        performanceFeeStrategist = _performanceFeeStrategist;
        emit SetPerformanceFeeStrategist(_performanceFeeStrategist);
    }

    /// @notice Sets the performance fee taken by the treasury on the harvests.
    ///         The fee is taken at the time of harvest reporting for both the underlying token and additional tokens.
    ///         For the underlying token, the fee is used to issue new shares for the treasury.
    ///         The new performance fee should be less than `maxPerformanceFee`.
    ///         This can be called by either governance or strategist.
    /// @dev See `reportHarvest` and `reportAdditionalToken` to see how performance fees are charged.
    /// @param _performanceFeeGovernance The new performance fee.
    function setPerformanceFeeGovernance(uint256 _performanceFeeGovernance) external whenNotPaused {
        _onlyGovernanceOrStrategist();
        require(_performanceFeeGovernance <= maxPerformanceFee, "Excessive governance performance fee");
        performanceFeeGovernance = _performanceFeeGovernance;
        emit SetPerformanceFeeGovernance(_performanceFeeGovernance);
    }

    /// @notice Sets the management fee taken by the treasury on the AUM in the sett.
    ///         The fee is calculated at the time of `reportHarvest` and is used to issue new shares for the treasury.
    ///         The new management fee should be less than `maxManagementFee`.
    ///         This can be called by either governance or strategist.
    /// @dev See `_handleFees` to see how the management fee is calculated.
    /// @param _fees The new management fee.
    function setManagementFee(uint256 _fees) external whenNotPaused {
        _onlyGovernanceOrStrategist();
        require(_fees <= maxManagementFee, "Excessive management fee");
        managementFee = _fees;
        emit SetManagementFee(_fees);
    }

    /// === Strategist level operations that can be done even when paused ==

    /// @notice Withdraws all funds from the strategy back to the sett.
    ///         This can be called by either governance or strategist.
    /// @dev This calls `_withdrawAll` on the strategy and transfers the balance to the sett.
    function withdrawToVault() external {
        _onlyGovernanceOrStrategist();
        IStrategy(strategy).withdrawToVault();
    }

    /// @notice Sends balance of any extra token earned by the strategy (from airdrops, donations etc.) 
    ///         to the badgerTree for emissions.
    ///         The `_token` should be different from any tokens managed by the strategy.
    ///         This can only be called by either strategist or governance.
    /// @dev See `BaseStrategy.emitNonProtectedToken` for details.
    /// @param _token Address of the token to be emitted.
    function emitNonProtectedToken(address _token) external {
        _onlyGovernanceOrStrategist();

        IStrategy(strategy).emitNonProtectedToken(_token);
    }

    /// @notice Sweeps the balance of an extra token from the vault and strategy and sends it to governance.
    ///         The `_token` should be different from any tokens managed by the strategy.
    ///         This can only be called by either strategist or governance.
    /// @dev Sweeping doesn't take any fee.
    /// @param _token Address of the token to be swept.
    function sweepExtraToken(address _token) external {
        _onlyGovernanceOrStrategist();
        require(address(token) != _token, "No want");

        IStrategy(strategy).withdrawOther(_token);
        // Send all `_token` we have
        // Safe because `withdrawOther` will revert on protected tokens  
        // Done this way works for both a donation to strategy or to vault
        IERC20Upgradeable(_token).safeTransfer(governance, IERC20Upgradeable(_token).balanceOf(address(this)));
    }

    /// @notice Deposits the available balance of the underlying token into the strategy.
    ///         The strategy then uses the amount for yield-generating activities.
    ///         This can be called by either the keeper or governance.
    ///         Note that earn cannot be called when deposits are paused.
    /// @dev Pause is enforced at the Strategy level (this allows to still earn yield when the Vault is paused)
    function earn() external {
        require(!pausedDeposit, "pausedDeposit"); // dev: deposits are paused, we don't earn as well
        _onlyAuthorizedActors();

        uint256 _bal = available();
        token.safeTransfer(strategy, _bal);
        IStrategy(strategy).earn();
    }

    /// @notice Pauses only deposits.
    ///         This can be called by either guardian or governance.
    function pauseDeposits() external {
        _onlyAuthorizedPausers();
        pausedDeposit = true;
        emit PauseDeposits(msg.sender);
    }
    
    /// @notice Unpauses deposits.
    ///         This can only be called by governance.
    function unpauseDeposits() external {
        _onlyGovernance();
        pausedDeposit = false;
        emit UnpauseDeposits(msg.sender);
    }

    /// @notice Pauses everything.
    ///         This can be called by either guardian or governance.
    function pause() external {
        _onlyAuthorizedPausers();
        _pause();
    }

    /// @notice Unpauses everything
    ///         This can only be called by governance.
    function unpause() external {
        _onlyGovernance();
        _unpause();
    }

    /// ===== Internal Implementations =====

    /// @notice Deposits `_amount` tokens, issuing shares to `recipient`. 
    ///         Note that deposits are not accepted when `pausedDeposit` is true. 
    /// @dev This is the actual deposit operation.
    ///      Deposits are based on the realized value of underlying assets between Sett & associated Strategy
    /// @param _recipient Address to issue the Sett shares to.
    /// @param _amount Quantity of tokens to deposit. 
    function _depositFor(address _recipient, uint256 _amount) internal nonReentrant {
        require(_recipient != address(0), "Address 0");
        require(_amount != 0, "Amount 0");
        require(!pausedDeposit, "pausedDeposit"); // dev: deposits are paused

        uint256 _pool = balance();
        uint256 _before = token.balanceOf(address(this));
        token.safeTransferFrom(msg.sender, address(this), _amount);
        uint256 _after = token.balanceOf(address(this));
        _mintSharesFor(_recipient, _after.sub(_before), _pool);
    }

    /// @dev See `_depositWithAuthorization`
    function _depositWithAuthorization(uint256 _amount, bytes32[] memory proof) internal {
        _depositForWithAuthorization(msg.sender, _amount, proof);
    }

    /// @dev Verifies that `_recipient` is authorized to deposit `_amount` based on the guestlist.
    ///      See `_depositFor` for deposit details.
    function _depositForWithAuthorization(
        address _recipient,
        uint256 _amount,
        bytes32[] memory proof
    ) internal {
        if (address(guestList) != address(0)) {
            require(guestList.authorized(_recipient, _amount, proof), "GuestList: Not Authorized");
        }
        _depositFor(_recipient, _amount);
    }


    /// @notice Redeems `_shares` for an appropriate amount of tokens.
    /// @dev This is the actual withdraw operation.
    ///      Withdraws from strategy positions if sett doesn't contain enough tokens to process the withdrawal. 
    ///      Calculates withdrawal fees and issues corresponding shares to treasury.
    ///      No rebalance implementation for lower fees and faster swaps
    /// @param _shares Quantity of shares to redeem. 
    function _withdraw(uint256 _shares) internal nonReentrant {
        require(_shares != 0, "0 Shares");

        uint256 r = (balance().mul(_shares)).div(totalSupply());
        _burn(msg.sender, _shares);

        // Check balance
        uint256 b = token.balanceOf(address(this));
        if (b < r) {
            uint256 _toWithdraw = r.sub(b);
            IStrategy(strategy).withdraw(_toWithdraw);
            uint256 _after = token.balanceOf(address(this));
            uint256 _diff = _after.sub(b);
            if (_diff < _toWithdraw) {
                r = b.add(_diff);
            }
        }
        uint256 _fee = _calculateFee(r, withdrawalFee);

        // Send funds to user
        token.safeTransfer(msg.sender, r.sub(_fee));

        // After you burned the shares, and you have sent the funds, adding here is equivalent to depositing
        // Process withdrawal fee
        if(_fee > 0) {
            _mintSharesFor(treasury, _fee, balance().sub(_fee));
        }
    }

    /// @dev Helper function to calculate fees.
    /// @param amount Amount to calculate fee on.
    /// @param feeBps The fee to be charged in basis points.
    /// @return Amount of fees to take.
    function _calculateFee(uint256 amount, uint256 feeBps) internal pure returns (uint256) {
        if (feeBps == 0) {
            return 0;
        }
        uint256 fee = amount.mul(feeBps).div(MAX_BPS);
        return fee;
    }

    /// @dev Helper function to calculate governance and strategist performance fees. Make sure to use it to get paid!
    /// @param _amount Amount to calculate fee on.
    /// @return Tuple containing amount of (governance, strategist) fees to take.
    function _calculatePerformanceFee(uint256 _amount)
        internal
        view
        returns (uint256, uint256)
    {
        uint256 governancePerformanceFee = _calculateFee(_amount, performanceFeeGovernance);

        uint256 strategistPerformanceFee = _calculateFee(_amount, performanceFeeStrategist);

        return (governancePerformanceFee, strategistPerformanceFee);
    }

    /// @dev Helper function to issue shares to `recipient` based on an input `_amount` and `_pool` size.
    /// @param recipient Address to issue shares to.
    /// @param _amount Amount to issue shares on.
    /// @param _pool Pool size to use while calculating amount of shares to mint.
    function _mintSharesFor(
        address recipient,
        uint256 _amount,
        uint256 _pool
    ) internal {
        uint256 shares;
        if (totalSupply() == 0) {
            shares = _amount;
        } else {
            shares = (_amount.mul(totalSupply())).div(_pool);
        }

        if(shares != 0) {
            _mint(recipient, shares);
        }
    }

    /// @dev Helper function that issues shares based on performance and management fee when a harvest is reported.
    /// @param _harvestedAmount The harvested amount to take fee on.
    /// @param harvestTime Time of harvest (block.timestamp).
    function _handleFees(uint256 _harvestedAmount, uint256 harvestTime) internal {
        (uint256 feeGovernance, uint256 feeStrategist) = _calculatePerformanceFee(_harvestedAmount);
        uint256 duration = harvestTime.sub(lastHarvestedAt);

        // Management fee is calculated against the assets before harvest, to make it fair to depositors
        uint256 management_fee = managementFee > 0 ? managementFee.mul(balance().sub(_harvestedAmount)).mul(duration).div(SECS_PER_YEAR).div(MAX_BPS) : 0;
        uint256 totalGovernanceFee = feeGovernance.add(management_fee);

        // Pool size is the size of the pool minus the fees, this way 
        // it's equivalent to sending the tokens as rewards after the harvest
        // and depositing them again
        uint256 _pool = balance().sub(totalGovernanceFee).sub(feeStrategist);

        // uint != is cheaper and equivalent to >
        if (totalGovernanceFee != 0) {
            _mintSharesFor(treasury, totalGovernanceFee, _pool);
        }

        if (feeStrategist != 0 && strategist != address(0)) {
            /// NOTE: adding feeGovernance backed to _pool as shares would have been issued for it.
            _mintSharesFor(strategist, feeStrategist, _pool.add(totalGovernanceFee));
        }
    }
}

File 3 of 16 : IERC20Upgradeable.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 IERC20Upgradeable {
    /**
     * @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 4 of 16 : SafeMathUpgradeable.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 SafeMathUpgradeable {
    /**
     * @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;
    }
}

File 5 of 16 : AddressUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @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);
    }

    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 6 of 16 : SafeERC20Upgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "IERC20Upgradeable.sol";
import "SafeMathUpgradeable.sol";
import "AddressUpgradeable.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 SafeERC20Upgradeable {
    using SafeMathUpgradeable for uint256;
    using AddressUpgradeable for address;

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

    function safeTransferFrom(IERC20Upgradeable 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(IERC20Upgradeable 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(IERC20Upgradeable 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(IERC20Upgradeable 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(IERC20Upgradeable 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 7 of 16 : ERC20Upgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "ContextUpgradeable.sol";
import "IERC20Upgradeable.sol";
import "SafeMathUpgradeable.sol";
import "Initializable.sol";

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

    mapping (address => uint256) private _balances;

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

    uint256 private _totalSupply;

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

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

    function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {
        _name = name_;
        _symbol = symbol_;
        _decimals = 18;
    }

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

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

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

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

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

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

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

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

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

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

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

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

        _beforeTokenTransfer(sender, recipient, amount);

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

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

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

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

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

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

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

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

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

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

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

File 8 of 16 : ContextUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;
import "Initializable.sol";

/*
 * @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 ContextUpgradeable is Initializable {
    function __Context_init() internal initializer {
        __Context_init_unchained();
    }

    function __Context_init_unchained() internal initializer {
    }
    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;
    }
    uint256[50] private __gap;
}

File 9 of 16 : Initializable.sol
// SPDX-License-Identifier: MIT

// solhint-disable-next-line compiler-version
pragma solidity >=0.4.24 <0.8.0;

import "AddressUpgradeable.sol";

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 */
abstract contract Initializable {

    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        require(_initializing || _isConstructor() || !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }

    /// @dev Returns true if and only if the function is running in the constructor
    function _isConstructor() private view returns (bool) {
        return !AddressUpgradeable.isContract(address(this));
    }
}

File 10 of 16 : PausableUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "ContextUpgradeable.sol";
import "Initializable.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    function __Pausable_init() internal initializer {
        __Context_init_unchained();
        __Pausable_init_unchained();
    }

    function __Pausable_init_unchained() internal initializer {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        require(!paused(), "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        require(paused(), "Pausable: not paused");
        _;
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
    uint256[49] private __gap;
}

File 11 of 16 : ReentrancyGuardUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;
import "Initializable.sol";

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuardUpgradeable is Initializable {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    function __ReentrancyGuard_init() internal initializer {
        __ReentrancyGuard_init_unchained();
    }

    function __ReentrancyGuard_init_unchained() internal initializer {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
    uint256[49] private __gap;
}

File 12 of 16 : SettAccessControl.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;

import "Initializable.sol";

/*
    Common base for permissioned roles throughout Sett ecosystem
*/
contract SettAccessControl is Initializable {
    address public governance;
    address public strategist;
    address public keeper;

    // ===== MODIFIERS =====
    function _onlyGovernance() internal view {
        require(msg.sender == governance, "onlyGovernance");
    }

    function _onlyGovernanceOrStrategist() internal view {
        require(msg.sender == strategist || msg.sender == governance, "onlyGovernanceOrStrategist");
    }

    function _onlyAuthorizedActors() internal view {
        require(msg.sender == keeper || msg.sender == governance, "onlyAuthorizedActors");
    }

    // ===== PERMISSIONED ACTIONS =====

    /// @notice Change strategist address
    /// @notice Can only be changed by governance itself
    function setStrategist(address _strategist) external {
        _onlyGovernance();
        strategist = _strategist;
    }

    /// @notice Change keeper address
    /// @notice Can only be changed by governance itself
    function setKeeper(address _keeper) external {
        _onlyGovernance();
        keeper = _keeper;
    }

    /// @notice Change governance address
    /// @notice Can only be changed by governance itself
    function setGovernance(address _governance) public {
        _onlyGovernance();
        governance = _governance;
    }

    uint256[50] private __gap;
}

File 13 of 16 : IVault.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.6.12;

interface IVault {
    function rewards() external view returns (address);

    function reportHarvest(
        uint256 _harvestedAmount
    ) external;

    function reportAdditionalToken(address _token) external;

    // Fees
    function performanceFeeGovernance() external view returns (uint256);

    function performanceFeeStrategist() external view returns (uint256);

    function withdrawalFee() external view returns (uint256);

    function managementFee() external view returns (uint256);

    // Actors
    function governance() external view returns (address);

    function keeper() external view returns (address);

    function guardian() external view returns (address);

    function strategist() external view returns (address);

    // External
    function deposit(uint256 _amount) external;
}

File 14 of 16 : IStrategy.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

interface IStrategy {
    // Return value for harvest, tend and balanceOfRewards
    struct TokenAmount {
        address token;
        uint256 amount;
    }

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

    function balanceOfPool() external view returns (uint256 balance);

    function balanceOfWant() external view returns (uint256 balance);

    function earn() external;

    function withdraw(uint256 amount) external;

    function withdrawToVault() external;

    function withdrawOther(address _asset) external;

    function harvest() external returns (TokenAmount[] memory harvested);
    function tend() external returns (TokenAmount[] memory tended);
    function balanceOfRewards() external view returns (TokenAmount[] memory rewards);

    function emitNonProtectedToken(address _token) external;
}

File 15 of 16 : IERC20Detailed.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.6.12;

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

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

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

    /**
     * @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 16 of 16 : BadgerGuestlistApi.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.7.0;

interface BadgerGuestListAPI {
    function authorized(
        address guest,
        uint256 amount,
        bytes32[] calldata merkleProof
    ) external view returns (bool);

    function setGuests(address[] calldata _guests, bool[] calldata _invited) external;
}

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

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"blockNumber","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"Harvested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pausedBy","type":"address"}],"name":"PauseDeposits","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newGuardian","type":"address"}],"name":"SetGuardian","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newGuestList","type":"address"}],"name":"SetGuestList","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newManagementFee","type":"uint256"}],"name":"SetManagementFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newMaxManagementFee","type":"uint256"}],"name":"SetMaxManagementFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newMaxPerformanceFee","type":"uint256"}],"name":"SetMaxPerformanceFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newMaxWithdrawalFee","type":"uint256"}],"name":"SetMaxWithdrawalFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newPerformanceFeeGovernance","type":"uint256"}],"name":"SetPerformanceFeeGovernance","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newPerformanceFeeStrategist","type":"uint256"}],"name":"SetPerformanceFeeStrategist","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newStrategy","type":"address"}],"name":"SetStrategy","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newEarnToBps","type":"uint256"}],"name":"SetToEarnBps","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newTreasury","type":"address"}],"name":"SetTreasury","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newWithdrawalFee","type":"uint256"}],"name":"SetWithdrawalFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"blockNumber","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"TreeDistribution","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pausedBy","type":"address"}],"name":"UnpauseDeposits","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"MANAGEMENT_FEE_HARD_CAP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERFORMANCE_FEE_HARD_CAP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECS_PER_YEAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WITHDRAWAL_FEE_HARD_CAP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"additionalTokensEarned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"assetsAtLastHarvest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"available","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"badgerTree","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"depositAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"depositFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"earn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"emitNonProtectedToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getPricePerFullShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guestList","outputs":[{"internalType":"contract BadgerGuestListAPI","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_governance","type":"address"},{"internalType":"address","name":"_keeper","type":"address"},{"internalType":"address","name":"_guardian","type":"address"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_strategist","type":"address"},{"internalType":"address","name":"_badgerTree","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint256[4]","name":"_feeConfig","type":"uint256[4]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"keeper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastAdditionalTokenAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastHarvestAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastHarvestedAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lifeTimeEarned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"managementFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxManagementFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPerformanceFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxWithdrawalFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pausedDeposit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"performanceFeeGovernance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"performanceFeeStrategist","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"reportAdditionalToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_harvestedAmount","type":"uint256"}],"name":"reportHarvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_governance","type":"address"}],"name":"setGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guardian","type":"address"}],"name":"setGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guestList","type":"address"}],"name":"setGuestList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_keeper","type":"address"}],"name":"setKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fees","type":"uint256"}],"name":"setManagementFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fees","type":"uint256"}],"name":"setMaxManagementFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fees","type":"uint256"}],"name":"setMaxPerformanceFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fees","type":"uint256"}],"name":"setMaxWithdrawalFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_performanceFeeGovernance","type":"uint256"}],"name":"setPerformanceFeeGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_performanceFeeStrategist","type":"uint256"}],"name":"setPerformanceFeeStrategist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategist","type":"address"}],"name":"setStrategist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategy","type":"address"}],"name":"setStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newToEarnBps","type":"uint256"}],"name":"setToEarnBps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_treasury","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_withdrawalFee","type":"uint256"}],"name":"setWithdrawalFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"strategist","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strategy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"sweepExtraToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toEarnBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20Upgradeable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawToVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawalFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b50614772806100206000396000f3fe608060405234801561001057600080fd5b50600436106104755760003560e01c80638457213a11610257578063c7b9d53011610146578063ec1c0a99116100c3578063f9f44f4e11610087578063f9f44f4e14610884578063fbdfdb441461088c578063fc0c546a14610894578063fd967f471461089c578063fe56e232146108a457610475565b8063ec1c0a991461083b578063ecb9da7714610843578063f0f442601461084b578063f55462f41461085e578063f7fec1811461087157610475565b8063dd62ed3e1161010a578063dd62ed3e146107fd578063de5f626814610810578063e06bacb714610818578063e782786c14610820578063eb4442e21461082857610475565b8063c7b9d530146107a9578063d389800f146107bc578063d6c2cadd146107c4578063dab7b06e146107d7578063dc7da299146107ea57610475565b8063a6f7f5d6116101d4578063aced166111610198578063aced166114610760578063b69ef8a814610768578063b6b55f2514610770578063bad91bdb14610783578063c783ee911461079657610475565b8063a6f7f5d614610717578063a8c62e761461071f578063a9059cbb14610727578063ab033ea91461073a578063ac1e50251461074d57610475565b80638bc7e8c41161021b5780638bc7e8c4146106ce57806395d89b41146106d6578063a0fd55e4146106de578063a234985e146106f1578063a457c2d71461070457610475565b80638457213a1461069057806384f22721146106a3578063853828b6146106ab57806389483695146106b35780638a0dac4a146106bb57610475565b80633f4ba83a1161037357806361d027b3116102f0578063748747e6116102b4578063748747e61461065d57806377c7b8fc146106705780637ca07723146106785780637dbe7920146106805780638456cb591461068857610475565b806361d027b31461062757806362be3cde1461062f57806363d8882a1461064257806364b03275146104ea57806370a082311461064a57610475565b8063504a164711610337578063504a1647146105ff5780635265ed611461060757806354fd4d501461060f5780635aa6e675146106175780635c975abb1461061f57610475565b80633f4ba83a146105cc578063452a9320146105d457806346d55875146105dc57806348a0d754146105e45780634c4c909b146105ec57610475565b80631fe4a686116104015780632f4f21e2116103c55780632f4f21e21461056b578063313ce5671461057e57806333a100ca1461059357806335ac79c3146105a657806339509351146105b957610475565b80631fe4a686146105155780632170121b1461052a57806323b872dd1461053d57806328998af0146105505780632e1a7d4d1461055857610475565b80630b5b78eb116104485780630b5b78eb146104d7578063130e9284146104ea57806315b18ddd146104f257806318160ddd146104fa5780631992a0881461050257610475565b8063021919801461047a57806306fdde0314610484578063095ea7b3146104a25780630b313206146104c2575b600080fd5b6104826108b7565b005b61048c6108ff565b6040516104999190613db1565b60405180910390f35b6104b56104b0366004613af2565b610996565b6040516104999190613da6565b6104ca6109b4565b60405161049991906145f6565b6104826104e5366004613973565b6109bb565b6104ca610a3b565b6104ca610a40565b6104ca610a47565b610482610510366004613c38565b610a4d565b61051d610ab7565b6040516104999190613cf8565b6104ca610538366004613973565b610ac6565b6104b561054b366004613ab2565b610ad9565b6104ca610b61565b610482610566366004613c38565b610b69565b610482610579366004613af2565b610b9a565b610586610bdf565b604051610499919061460d565b6104826105a1366004613973565b610be8565b6104826105b4366004613c68565b610d3c565b6104b56105c7366004613af2565b610d6b565b610482610db9565b61051d610dcb565b61051d610ddb565b6104ca610dea565b6104826105fa366004613973565b610e8d565b6104ca61110c565b6104ca611113565b61048c61111a565b61051d611137565b6104b5611146565b61051d61114f565b61048261063d366004613c38565b61115f565b6104826111e4565b6104ca610658366004613973565b611226565b61048261066b366004613973565b611241565b6104ca61126b565b6104ca6112a7565b6104ca6112ad565b6104826112b4565b61048261069e366004613c38565b6112c4565b61048261134a565b6104826113bd565b61051d6113f3565b6104826106c9366004613973565b611403565b6104ca61147c565b61048c611483565b6104826106ec366004613973565b6114e4565b6104826106ff366004613973565b611552565b6104b5610712366004613af2565b611684565b6104ca6116ec565b61051d6116f3565b6104b5610735366004613af2565b611703565b610482610748366004613973565b611717565b61048261075b366004613c38565b611741565b61051d6117c7565b6104ca6117d6565b61048261077e366004613c38565b6118e8565b610482610791366004613b72565b611945565b6104ca6107a4366004613973565b6119f2565b6104826107b7366004613973565b611a05565b610482611a2f565b6104826107d2366004613b1c565b611adc565b6104826107e5366004613c38565b611b11565b6104826107f8366004613c38565b611b71565b6104ca61080b36600461398e565b611c50565b610482611c7b565b6104b5611d2a565b6104ca611d39565b610482610836366004613c38565b611d40565b6104ca611d9f565b6104ca611da6565b610482610859366004613973565b611dad565b61048261086c366004613c38565b611e4b565b61048261087f3660046139c2565b611ed1565b6104ca612443565b6104ca61244a565b61051d612451565b6104ca612460565b6104826108b2366004613c38565b612466565b6108bf6124ec565b60ff805460ff60a01b1916600160a01b17905560405133907fd7a915337e28a7bf3a13770590fb6701cbeb9d0f25a71e84d106b10a8e6a4ab190600090a2565b60368054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561098b5780601f106109605761010080835404028352916020019161098b565b820191906000526020600020905b81548152906001019060200180831161096e57829003601f168201915b505050505090505b90565b60006109aa6109a361252c565b8484612530565b5060015b92915050565b6101105481565b6109c3611146565b156109e95760405162461bcd60e51b81526004016109e0906140ac565b60405180910390fd5b6109f16125e4565b60ff80546001600160a01b0319166001600160a01b0383169081179091556040517fcf4ebfb08408f66bc4a7a6945a6842089eeee844a2cc7615e8cf517ce520f3da90600090a250565b60c881565b61010a5481565b60355490565b610a55612623565b60c8811115610a765760405162461bcd60e51b81526004016109e0906144ca565b61010f8190556040517fa254b26086a7ddac6321f8f7b7ae1301e48e0734fc6ad56fb6a4eb58dbd8c49c90610aac9083906145f6565b60405180910390a150565b6066546001600160a01b031681565b6101086020526000908152604090205481565b6000610ae684848461264d565b610b5684610af261252c565b610b51856040518060600160405280602881526020016146f0602891396001600160a01b038a16600090815260346020526040812090610b3061252c565b6001600160a01b031681526020810191909152604001600020549190612762565b612530565b5060015b9392505050565b6301e1855881565b610b71611146565b15610b8e5760405162461bcd60e51b81526004016109e0906140ac565b610b978161278e565b50565b610ba2611146565b15610bbf5760405162461bcd60e51b81526004016109e0906140ac565b604080516000815260208101909152610bdb9083908390612a05565b5050565b60385460ff1690565b610bf0611146565b15610c0d5760405162461bcd60e51b81526004016109e0906140ac565b610c15612623565b6001600160a01b038116610c3b5760405162461bcd60e51b81526004016109e090613fd7565b610100546001600160a01b031615610cf15761010060009054906101000a90046001600160a01b03166001600160a01b031663722713f76040518163ffffffff1660e01b815260040160206040518083038186803b158015610c9c57600080fd5b505afa158015610cb0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd49190613c50565b15610cf15760405162461bcd60e51b81526004016109e090613e83565b61010080546001600160a01b0319166001600160a01b0383169081179091556040517f3412691e1ea2503d6eec15597247048016213c19646b73d4320a20c790b67ee290600090a250565b610d44611146565b15610d615760405162461bcd60e51b81526004016109e0906140ac565b610bdb8282612ac0565b60006109aa610d7861252c565b84610b518560346000610d8961252c565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490612acb565b610dc1612623565b610dc9612af0565b565b610101546001600160a01b031681565b60ff546001600160a01b031681565b6101115460fe546040516370a0823160e01b8152600092610e889261271092610e8292916001600160a01b0316906370a0823190610e2c903090600401613cf8565b60206040518083038186803b158015610e4457600080fd5b505afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c9190613c50565b90612b5e565b90612b98565b905090565b600260cc541415610eb05760405162461bcd60e51b81526004016109e090614522565b600260cc55610ebd612bca565b60fe546001600160a01b0382811691161415610eeb5760405162461bcd60e51b81526004016109e090613fb6565b6040516370a0823160e01b81526000906001600160a01b038316906370a0823190610f1a903090600401613cf8565b60206040518083038186803b158015610f3257600080fd5b505afa158015610f46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f6a9190613c50565b6001600160a01b03831660009081526101086020526040902054909150610f919082612acb565b6001600160a01b03831660009081526101086020908152604080832093909355610109905290812082905561010a54610fcb908390612bf5565b90506000610fdc8361010b54612bf5565b90508115610fff5761010254610fff906001600160a01b03868116911684612c1e565b801561101f5760665461101f906001600160a01b03868116911683612c1e565b6040516370a0823160e01b81526000906001600160a01b038616906370a082319061104e903090600401613cf8565b60206040518083038186803b15801561106657600080fd5b505afa15801561107a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109e9190613c50565b610103549091506110bc906001600160a01b03878116911683612c1e565b43856001600160a01b03167f17cc18c044bdfa5f365fb0f6140ffbaa76843012681aedb2015580693fa49b9483426040516110f89291906145ff565b60405180910390a35050600160cc55505050565b61010b5481565b61010e5481565b604080518082019091526003815262312e3560e81b602082015290565b6065546001600160a01b031681565b609a5460ff1690565b610102546001600160a01b031681565b611167611146565b156111845760405162461bcd60e51b81526004016109e0906140ac565b61118c6125e4565b6127108111156111ae5760405162461bcd60e51b81526004016109e090613f11565b6101118190556040517f5cc7e39e46826190c353c144fe457f6621996ec0f604b3d78e3ac26fd1b4bde290610aac9083906145f6565b6111ec612623565b60ff805460ff60a01b1916905560405133907f136ece421d83ae8c5fe0d9b95b96b35315050bfc3cf21cb5751128f683eb59be90600090a2565b6001600160a01b031660009081526033602052604090205490565b611249612623565b606780546001600160a01b0319166001600160a01b0392909216919091179055565b6000611275610a47565b6112885750670de0b6b3a7640000610993565b610e88611293610a47565b610e82670de0b6b3a7640000610e7c6117d6565b610bb881565b6101065481565b6112bc6124ec565b610dc9612c74565b6112cc611146565b156112e95760405162461bcd60e51b81526004016109e0906140ac565b6112f16125e4565b61010e548111156113145760405162461bcd60e51b81526004016109e090613ffa565b61010a8190556040517f1776ab2b6ca2ecf6879162cd3f7f99594a9d5b67ac64d0d41e63f1e804969ef290610aac9083906145f6565b6113526125e4565b61010060009054906101000a90046001600160a01b03166001600160a01b03166384f227216040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156113a357600080fd5b505af11580156113b7573d6000803e3d6000fd5b50505050565b6113c5611146565b156113e25760405162461bcd60e51b81526004016109e0906140ac565b610dc96113ee33611226565b61278e565b610103546001600160a01b031681565b61140b612623565b6001600160a01b0381166114315760405162461bcd60e51b81526004016109e09061449b565b61010180546001600160a01b0319166001600160a01b0383169081179091556040517f31845eceb9cde510c7e8b37f76301c688feb70bc9653aa4c28a3734999840fd890600090a250565b61010c5481565b60378054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561098b5780601f106109605761010080835404028352916020019161098b565b6114ec6125e4565b6101005460405163283f557960e21b81526001600160a01b039091169063a0fd55e49061151d908490600401613cf8565b600060405180830381600087803b15801561153757600080fd5b505af115801561154b573d6000803e3d6000fd5b5050505050565b61155a6125e4565b60fe546001600160a01b03828116911614156115885760405162461bcd60e51b81526004016109e090613fb6565b61010054604051631bd43be360e01b81526001600160a01b0390911690631bd43be3906115b9908490600401613cf8565b600060405180830381600087803b1580156115d357600080fd5b505af11580156115e7573d6000803e3d6000fd5b50506065546040516370a0823160e01b8152610b9793506001600160a01b039182169250908416906370a0823190611623903090600401613cf8565b60206040518083038186803b15801561163b57600080fd5b505afa15801561164f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116739190613c50565b6001600160a01b0384169190612c1e565b60006109aa61169161252c565b84610b518560405180606001604052806025815260200161471860259139603460006116bb61252c565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190612762565b61010d5481565b610100546001600160a01b031681565b60006109aa61171061252c565b848461264d565b61171f612623565b606580546001600160a01b0319166001600160a01b0392909216919091179055565b611749611146565b156117665760405162461bcd60e51b81526004016109e0906140ac565b61176e6125e4565b61010f548111156117915760405162461bcd60e51b81526004016109e09061419c565b61010c8190556040517f3aa4413905e8f015896ec5880bdde24088ccb19b578f9fcf6800354d5320d4af90610aac9083906145f6565b6067546001600160a01b031681565b6000610e8861010060009054906101000a90046001600160a01b03166001600160a01b031663722713f76040518163ffffffff1660e01b815260040160206040518083038186803b15801561182a57600080fd5b505afa15801561183e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118629190613c50565b60fe546040516370a0823160e01b81526001600160a01b03909116906370a0823190611892903090600401613cf8565b60206040518083038186803b1580156118aa57600080fd5b505afa1580156118be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e29190613c50565b90612acb565b6118f0611146565b1561190d5760405162461bcd60e51b81526004016109e0906140ac565b610b97816000805b5060405190808252806020026020018201604052801561193f578160200160208202803683370190505b50612ac0565b61194d611146565b1561196a5760405162461bcd60e51b81526004016109e0906140ac565b60fe546040516370a0823160e01b8152610b97916001600160a01b0316906370a082319061199c903390600401613cf8565b60206040518083038186803b1580156119b457600080fd5b505afa1580156119c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ec9190613c50565b82612ac0565b6101096020526000908152604090205481565b611a0d612623565b606680546001600160a01b0319166001600160a01b0392909216919091179055565b60ff8054600160a01b90041615611a585760405162461bcd60e51b81526004016109e09061426d565b611a60612ccf565b6000611a6a610dea565b6101005460fe54919250611a8b916001600160a01b03908116911683612c1e565b61010060009054906101000a90046001600160a01b03166001600160a01b031663d389800f6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561153757600080fd5b611ae4611146565b15611b015760405162461bcd60e51b81526004016109e0906140ac565b611b0c838383612a05565b505050565b611b19612623565b610bb8811115611b3b5760405162461bcd60e51b81526004016109e09061420a565b61010e8190556040517fd7fabec26d79f18c91fcbf04b6e1650fcd90cd4f7d6c389feeca8339c012f9bb90610aac9083906145f6565b600260cc541415611b945760405162461bcd60e51b81526004016109e090614522565b600260cc55611ba1612bca565b426000611bb683611bb06117d6565b90612d0e565b9050611bc28383612d36565b6101068390558015611bd957610107819055611be5565b82611be5576000610107555b61010454611bf39084612acb565b6101045561010582905560fe5460405143916001600160a01b0316907fe48bba143e2a0b557fa6f3234bd6ffc704518cc98c7de6a2385549fae27d1b7590611c3e90879042906145ff565b60405180910390a35050600160cc5550565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b611c83611146565b15611ca05760405162461bcd60e51b81526004016109e0906140ac565b60fe546040516370a0823160e01b8152610dc9916001600160a01b0316906370a0823190611cd2903390600401613cf8565b60206040518083038186803b158015611cea57600080fd5b505afa158015611cfe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d229190613c50565b600080611915565b60ff8054600160a01b90041681565b6101075481565b611d48612623565b60c8811115611d695760405162461bcd60e51b81526004016109e0906142fa565b6101108190556040517f4c7b8194b874abd9829fc99a7fd17528dd31a043b15b067e806b9aed5e2febb390610aac9083906145f6565b61010f5481565b6101055481565b611db5611146565b15611dd25760405162461bcd60e51b81526004016109e0906140ac565b611dda612623565b6001600160a01b038116611e005760405162461bcd60e51b81526004016109e090613fd7565b61010280546001600160a01b0319166001600160a01b0383169081179091556040517fcb7ef3e545f5cdb893f5c568ba710fe08f336375a2d9fd66e161033f8fc09ef390600090a250565b611e53611146565b15611e705760405162461bcd60e51b81526004016109e0906140ac565b611e786125e4565b61010e54811115611e9b5760405162461bcd60e51b81526004016109e090614559565b61010b8190556040517fa2b496c086c66c1966a950920059fb82fdb25b562982c79b2aa490fde65f647b90610aac9083906145f6565b600054610100900460ff1680611eea5750611eea612e23565b80611ef8575060005460ff16155b611f145760405162461bcd60e51b81526004016109e09061410d565b600054610100900460ff16158015611f3f576000805460ff1961ff0019909116610100171660011790555b611f47611146565b15611f645760405162461bcd60e51b81526004016109e0906140ac565b6001600160a01b038b16611f7757600080fd5b6001600160a01b038a16611f8a57600080fd5b6001600160a01b038916611f9d57600080fd5b6001600160a01b038816611fb057600080fd5b6001600160a01b038716611fc357600080fd5b6001600160a01b038616611fd657600080fd5b6001600160a01b038516611fe957600080fd5b8151610bb8101561200c5760405162461bcd60e51b81526004016109e09061436f565b6020820151610bb810156120325760405162461bcd60e51b81526004016109e09061420a565b604082015160c810156120575760405162461bcd60e51b81526004016109e0906144ca565b606082015160c8101561207c5760405162461bcd60e51b81526004016109e0906142fa565b60608060008d90507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470876040516020016120b69190613cad565b60405160208183030381529060405280519060200120146120d957869250612196565b6040518060400160405280600c81526020016b02130b233b2b91029b2ba3a160a51b815250816001600160a01b03166306fdde036040518163ffffffff1660e01b815260040160006040518083038186803b15801561213757600080fd5b505afa15801561214b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526121739190810190613bc5565b604051602001612184929190613cc9565b60405160208183030381529060405292505b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470866040516020016121c89190613cad565b60405160208183030381529060405280519060200120146121eb5785915061229d565b604051806040016040528060018152602001603160f91b815250816001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801561223e57600080fd5b505afa158015612252573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261227a9190810190613bc5565b60405160200161228b929190613cc9565b60405160208183030381529060405291505b6122a78383612e34565b6122af612eca565b6122b7612f5c565b8d60fe60006101000a8154816001600160a01b0302191690836001600160a01b031602179055508c606560006101000a8154816001600160a01b0302191690836001600160a01b031602179055508961010260006101000a8154816001600160a01b0302191690836001600160a01b0316021790555088606660006101000a8154816001600160a01b0302191690836001600160a01b031602179055508b606760006101000a8154816001600160a01b0302191690836001600160a01b031602179055508a61010160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508761010360006101000a8154816001600160a01b0302191690836001600160a01b031602179055504261010581905550846000600481106123e057fe5b6020908102919091015161010a5585015161010b55505050604082015161010c55606082015161010d55610bb861010e5560c861010f8190556101105561251c610111558015612436576000805461ff00191690555b5050505050505050505050565b6101045481565b6101115481565b60fe546001600160a01b031681565b61271081565b61246e611146565b1561248b5760405162461bcd60e51b81526004016109e0906140ac565b6124936125e4565b610110548111156124b65760405162461bcd60e51b81526004016109e090613f48565b61010d8190556040517fd87632b1c6ebfa21acbca0e3279b3cf6385a377cb8fda51e5b866baa6e6012ab90610aac9083906145f6565b610101546001600160a01b031633148061251057506065546001600160a01b031633145b610dc95760405162461bcd60e51b81526004016109e0906142d5565b3390565b6001600160a01b0383166125565760405162461bcd60e51b81526004016109e0906143b0565b6001600160a01b03821661257c5760405162461bcd60e51b81526004016109e090613ecf565b6001600160a01b0380841660008181526034602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906125d79085906145f6565b60405180910390a3505050565b6066546001600160a01b031633148061260757506065546001600160a01b031633145b610dc95760405162461bcd60e51b81526004016109e0906140d6565b6065546001600160a01b03163314610dc95760405162461bcd60e51b81526004016109e0906144fa565b6001600160a01b0383166126735760405162461bcd60e51b81526004016109e09061432a565b6001600160a01b0382166126995760405162461bcd60e51b81526004016109e090613e12565b6126a4838383611b0c565b6126e1816040518060600160405280602681526020016146ca602691396001600160a01b0386166000908152603360205260409020549190612762565b6001600160a01b0380851660009081526033602052604080822093909355908416815220546127109082612acb565b6001600160a01b0380841660008181526033602052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906125d79085906145f6565b600081848411156127865760405162461bcd60e51b81526004016109e09190613db1565b505050900390565b600260cc5414156127b15760405162461bcd60e51b81526004016109e090614522565b600260cc55806127d35760405162461bcd60e51b81526004016109e09061424b565b60006127ec6127e0610a47565b610e8284610e7c6117d6565b90506127f83383612fd2565b60fe546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612829903090600401613cf8565b60206040518083038186803b15801561284157600080fd5b505afa158015612855573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128799190613c50565b90508181101561299f57600061288f8383612d0e565b61010054604051632e1a7d4d60e01b81529192506001600160a01b031690632e1a7d4d906128c19084906004016145f6565b600060405180830381600087803b1580156128db57600080fd5b505af11580156128ef573d6000803e3d6000fd5b505060fe546040516370a0823160e01b8152600093506001600160a01b0390911691506370a0823190612926903090600401613cf8565b60206040518083038186803b15801561293e57600080fd5b505afa158015612952573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129769190613c50565b905060006129848285612d0e565b90508281101561299b576129988482612acb565b94505b5050505b60006129ae8361010c54612bf5565b90506129d1336129be8584612d0e565b60fe546001600160a01b03169190612c1e565b80156129fa57610102546129fa906001600160a01b0316826129f581611bb06117d6565b6130b4565b5050600160cc555050565b60ff546001600160a01b031615612ab65760ff54604051631a9ee26f60e01b81526001600160a01b0390911690631a9ee26f90612a4a90869086908690600401613d49565b60206040518083038186803b158015612a6257600080fd5b505afa158015612a76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a9a9190613ba5565b612ab65760405162461bcd60e51b81526004016109e0906141d3565b611b0c83836130f2565b610bdb338383612a05565b600082820183811015610b5a5760405162461bcd60e51b81526004016109e090613f7f565b612af8611146565b612b145760405162461bcd60e51b81526004016109e090613e55565b609a805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612b4761252c565b604051612b549190613cf8565b60405180910390a1565b600082612b6d575060006109ae565b82820282848281612b7a57fe5b0414610b5a5760405162461bcd60e51b81526004016109e09061415b565b6000808211612bb95760405162461bcd60e51b81526004016109e090614075565b818381612bc257fe5b049392505050565b610100546001600160a01b03163314610dc95760405162461bcd60e51b81526004016109e09061442b565b600081612c04575060006109ae565b6000612c16612710610e828686612b5e565b949350505050565b611b0c8363a9059cbb60e01b8484604051602401612c3d929190613d30565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526132d4565b612c7c611146565b15612c995760405162461bcd60e51b81526004016109e0906140ac565b609a805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612b4761252c565b6067546001600160a01b0316331480612cf257506065546001600160a01b031633145b610dc95760405162461bcd60e51b81526004016109e090613de4565b600082821115612d305760405162461bcd60e51b81526004016109e09061403e565b50900390565b600080612d4284613363565b915091506000612d5e6101055485612d0e90919063ffffffff16565b905060008061010d5411612d73576000612d9e565b612d9e612710610e826301e18558610e8286610e7c612d948d611bb06117d6565b61010d5490612b5e565b90506000612dac8583612acb565b90506000612dc085611bb084611bb06117d6565b90508115612de05761010254612de0906001600160a01b031683836130b4565b8415801590612df957506066546001600160a01b031615155b15612e1957606654612e19906001600160a01b0316866129f58486612acb565b5050505050505050565b6000612e2e30613392565b15905090565b600054610100900460ff1680612e4d5750612e4d612e23565b80612e5b575060005460ff16155b612e775760405162461bcd60e51b81526004016109e09061410d565b600054610100900460ff16158015612ea2576000805460ff1961ff0019909116610100171660011790555b612eaa613398565b612eb48383613419565b8015611b0c576000805461ff0019169055505050565b600054610100900460ff1680612ee35750612ee3612e23565b80612ef1575060005460ff16155b612f0d5760405162461bcd60e51b81526004016109e09061410d565b600054610100900460ff16158015612f38576000805460ff1961ff0019909116610100171660011790555b612f40613398565b612f486134d2565b8015610b97576000805461ff001916905550565b600054610100900460ff1680612f755750612f75612e23565b80612f83575060005460ff16155b612f9f5760405162461bcd60e51b81526004016109e09061410d565b600054610100900460ff16158015612fca576000805460ff1961ff0019909116610100171660011790555b612f4861355e565b6001600160a01b038216612ff85760405162461bcd60e51b81526004016109e090614294565b61300482600083611b0c565b613041816040518060600160405280602281526020016146a8602291396001600160a01b0385166000908152603360205260409020549190612762565b6001600160a01b0383166000908152603360205260409020556035546130679082612d0e565b6035556040516000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906130a89085906145f6565b60405180910390a35050565b60006130be610a47565b6130c95750816130e2565b6130df82610e826130d8610a47565b8690612b5e565b90505b80156113b7576113b784826135e5565b600260cc5414156131155760405162461bcd60e51b81526004016109e090614522565b600260cc556001600160a01b0382166131405760405162461bcd60e51b81526004016109e090613fd7565b8061315d5760405162461bcd60e51b81526004016109e09061459d565b60ff8054600160a01b900416156131865760405162461bcd60e51b81526004016109e09061426d565b60006131906117d6565b60fe546040516370a0823160e01b81529192506000916001600160a01b03909116906370a08231906131c6903090600401613cf8565b60206040518083038186803b1580156131de57600080fd5b505afa1580156131f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132169190613c50565b60fe54909150613231906001600160a01b0316333086613699565b60fe546040516370a0823160e01b81526000916001600160a01b0316906370a0823190613262903090600401613cf8565b60206040518083038186803b15801561327a57600080fd5b505afa15801561328e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132b29190613c50565b90506132c8856132c28385612d0e565b856130b4565b5050600160cc55505050565b6060613329826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166136ba9092919063ffffffff16565b805190915015611b0c57808060200190518101906133479190613ba5565b611b0c5760405162461bcd60e51b81526004016109e090614451565b60008060006133758461010a54612bf5565b905060006133868561010b54612bf5565b91935090915050915091565b3b151590565b600054610100900460ff16806133b157506133b1612e23565b806133bf575060005460ff16155b6133db5760405162461bcd60e51b81526004016109e09061410d565b600054610100900460ff16158015612f48576000805460ff1961ff0019909116610100171660011790558015610b97576000805461ff001916905550565b600054610100900460ff16806134325750613432612e23565b80613440575060005460ff16155b61345c5760405162461bcd60e51b81526004016109e09061410d565b600054610100900460ff16158015613487576000805460ff1961ff0019909116610100171660011790555b825161349a90603690602086019061379d565b5081516134ae90603790602085019061379d565b506038805460ff191660121790558015611b0c576000805461ff0019169055505050565b600054610100900460ff16806134eb57506134eb612e23565b806134f9575060005460ff16155b6135155760405162461bcd60e51b81526004016109e09061410d565b600054610100900460ff16158015613540576000805460ff1961ff0019909116610100171660011790555b609a805460ff191690558015610b97576000805461ff001916905550565b600054610100900460ff16806135775750613577612e23565b80613585575060005460ff16155b6135a15760405162461bcd60e51b81526004016109e09061410d565b600054610100900460ff161580156135cc576000805460ff1961ff0019909116610100171660011790555b600160cc558015610b97576000805461ff001916905550565b6001600160a01b03821661360b5760405162461bcd60e51b81526004016109e0906145bf565b61361760008383611b0c565b6035546136249082612acb565b6035556001600160a01b03821660009081526033602052604090205461364a9082612acb565b6001600160a01b0383166000818152603360205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906130a89085906145f6565b6113b7846323b872dd60e01b858585604051602401612c3d93929190613d0c565b6060612c168484600085856136ce85613392565b6136ea5760405162461bcd60e51b81526004016109e0906143f4565b60006060866001600160a01b031685876040516137079190613cad565b60006040518083038185875af1925050503d8060008114613744576040519150601f19603f3d011682016040523d82523d6000602084013e613749565b606091505b5091509150613759828286613764565b979650505050505050565b60608315613773575081610b5a565b8251156137835782518084602001fd5b8160405162461bcd60e51b81526004016109e09190613db1565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106137de57805160ff191683800117855561380b565b8280016001018555821561380b579182015b8281111561380b5782518255916020019190600101906137f0565b5061381792915061381b565b5090565b5b80821115613817576000815560010161381c565b80356001600160a01b03811681146109ae57600080fd5b600082601f830112613857578081fd5b813567ffffffffffffffff81111561386d578182fd5b602080820261387d82820161461b565b8381529350818401858301828701840188101561389957600080fd5b600092505b848310156138bc57803582526001929092019190830190830161389e565b505050505092915050565b600082601f8301126138d7578081fd5b6138e1608061461b565b90508082846080850111156138f557600080fd5b60005b60048110156139175781358352602092830192909101906001016138f8565b50505092915050565b600082601f830112613930578081fd5b813561394361393e82614642565b61461b565b915080825283602082850101111561395a57600080fd5b8060208401602084013760009082016020015292915050565b600060208284031215613984578081fd5b610b5a8383613830565b600080604083850312156139a0578081fd5b6139aa8484613830565b91506139b98460208501613830565b90509250929050565b6000806000806000806000806000806101a08b8d0312156139e1578586fd5b6139eb8c8c613830565b99506139fa8c60208d01613830565b9850613a098c60408d01613830565b9750613a188c60608d01613830565b9650613a278c60808d01613830565b9550613a368c60a08d01613830565b9450613a458c60c08d01613830565b935060e08b013567ffffffffffffffff80821115613a61578485fd5b613a6d8e838f01613920565b94506101008d0135915080821115613a83578384fd5b50613a908d828e01613920565b925050613aa18c6101208d016138c7565b90509295989b9194979a5092959850565b600080600060608486031215613ac6578283fd5b8335613ad181614692565b92506020840135613ae181614692565b929592945050506040919091013590565b60008060408385031215613b04578182fd5b613b0e8484613830565b946020939093013593505050565b600080600060608486031215613b30578283fd5b613b3a8585613830565b925060208401359150604084013567ffffffffffffffff811115613b5c578182fd5b613b6886828701613847565b9150509250925092565b600060208284031215613b83578081fd5b813567ffffffffffffffff811115613b99578182fd5b612c1684828501613847565b600060208284031215613bb6578081fd5b81518015158114610b5a578182fd5b600060208284031215613bd6578081fd5b815167ffffffffffffffff811115613bec578182fd5b8201601f81018413613bfc578182fd5b8051613c0a61393e82614642565b818152856020838501011115613c1e578384fd5b613c2f826020830160208601614666565b95945050505050565b600060208284031215613c49578081fd5b5035919050565b600060208284031215613c61578081fd5b5051919050565b60008060408385031215613c7a578081fd5b82359150602083013567ffffffffffffffff811115613c97578182fd5b613ca385828601613847565b9150509250929050565b60008251613cbf818460208701614666565b9190910192915050565b60008351613cdb818460208801614666565b835190830190613cef818360208801614666565b01949350505050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b038416815260208082018490526060604083018190528351908301819052600091848101916080850190845b81811015613d9857845183529383019391830191600101613d7c565b509098975050505050505050565b901515815260200190565b6000602082528251806020840152613dd0816040850160208701614666565b601f01601f19169190910160400192915050565b6020808252601490820152736f6e6c79417574686f72697a65644163746f727360601b604082015260600190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526014908201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604082015260600190565b6020808252602c908201527f506c65617365207769746864726177546f5661756c74206265666f726520636860408201526b185b99da5b99c81cdd1c985d60a21b606082015260800190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252601e908201527f746f4561726e4270732073686f756c64206265203c3d204d41585f4250530000604082015260600190565b60208082526018908201527f457863657373697665206d616e6167656d656e74206665650000000000000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b602080825260079082015266139bc81dd85b9d60ca1b604082015260600190565b60208082526009908201526804164647265737320360bc1b604082015260600190565b60208082526024908201527f45786365737369766520676f7665726e616e636520706572666f726d616e63656040820152632066656560e01b606082015260800190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252601a908201527f6f6e6c79476f7665726e616e63654f7253747261746567697374000000000000604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526018908201527f457863657373697665207769746864726177616c206665650000000000000000604082015260600190565b60208082526019908201527f47756573744c6973743a204e6f7420417574686f72697a656400000000000000604082015260600190565b60208082526021908201527f706572666f726d616e63654665655374726174656769737420746f6f206869676040820152600d60fb1b606082015260800190565b602080825260089082015267302053686172657360c01b604082015260600190565b6020808252600d908201526c1c185d5cd95911195c1bdcda5d609a1b604082015260600190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b6020808252600b908201526a6f6e6c795061757365727360a81b604082015260600190565b6020808252601690820152750dac2dcc2cecadacadce88ccaca40e8dede40d0d2ced60531b604082015260600190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526021908201527f706572666f726d616e6365466565476f7665726e616e636520746f6f206869676040820152600d60fb1b606082015260800190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600c908201526b6f6e6c79537472617465677960a01b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252601590820152740416464726573732063616e6e6f742062652030783605c1b604082015260600190565b6020808252601690820152750eed2e8d0c8e4c2eec2d88ccaca40e8dede40d0d2ced60531b604082015260600190565b6020808252600e908201526d6f6e6c79476f7665726e616e636560901b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60208082526024908201527f457863657373697665207374726174656769737420706572666f726d616e63656040820152632066656560e01b606082015260800190565b6020808252600890820152670416d6f756e7420360c41b604082015260600190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b90815260200190565b918252602082015260400190565b60ff91909116815260200190565b60405181810167ffffffffffffffff8111828210171561463a57600080fd5b604052919050565b600067ffffffffffffffff821115614658578081fd5b50601f01601f191660200190565b60005b83811015614681578181015183820152602001614669565b838111156113b75750506000910152565b6001600160a01b0381168114610b9757600080fdfe45524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212200a6ce01bfd967533edb93dde951933f743c58cb33e26e1409a62d09c14bb151d64736f6c634300060c0033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106104755760003560e01c80638457213a11610257578063c7b9d53011610146578063ec1c0a99116100c3578063f9f44f4e11610087578063f9f44f4e14610884578063fbdfdb441461088c578063fc0c546a14610894578063fd967f471461089c578063fe56e232146108a457610475565b8063ec1c0a991461083b578063ecb9da7714610843578063f0f442601461084b578063f55462f41461085e578063f7fec1811461087157610475565b8063dd62ed3e1161010a578063dd62ed3e146107fd578063de5f626814610810578063e06bacb714610818578063e782786c14610820578063eb4442e21461082857610475565b8063c7b9d530146107a9578063d389800f146107bc578063d6c2cadd146107c4578063dab7b06e146107d7578063dc7da299146107ea57610475565b8063a6f7f5d6116101d4578063aced166111610198578063aced166114610760578063b69ef8a814610768578063b6b55f2514610770578063bad91bdb14610783578063c783ee911461079657610475565b8063a6f7f5d614610717578063a8c62e761461071f578063a9059cbb14610727578063ab033ea91461073a578063ac1e50251461074d57610475565b80638bc7e8c41161021b5780638bc7e8c4146106ce57806395d89b41146106d6578063a0fd55e4146106de578063a234985e146106f1578063a457c2d71461070457610475565b80638457213a1461069057806384f22721146106a3578063853828b6146106ab57806389483695146106b35780638a0dac4a146106bb57610475565b80633f4ba83a1161037357806361d027b3116102f0578063748747e6116102b4578063748747e61461065d57806377c7b8fc146106705780637ca07723146106785780637dbe7920146106805780638456cb591461068857610475565b806361d027b31461062757806362be3cde1461062f57806363d8882a1461064257806364b03275146104ea57806370a082311461064a57610475565b8063504a164711610337578063504a1647146105ff5780635265ed611461060757806354fd4d501461060f5780635aa6e675146106175780635c975abb1461061f57610475565b80633f4ba83a146105cc578063452a9320146105d457806346d55875146105dc57806348a0d754146105e45780634c4c909b146105ec57610475565b80631fe4a686116104015780632f4f21e2116103c55780632f4f21e21461056b578063313ce5671461057e57806333a100ca1461059357806335ac79c3146105a657806339509351146105b957610475565b80631fe4a686146105155780632170121b1461052a57806323b872dd1461053d57806328998af0146105505780632e1a7d4d1461055857610475565b80630b5b78eb116104485780630b5b78eb146104d7578063130e9284146104ea57806315b18ddd146104f257806318160ddd146104fa5780631992a0881461050257610475565b8063021919801461047a57806306fdde0314610484578063095ea7b3146104a25780630b313206146104c2575b600080fd5b6104826108b7565b005b61048c6108ff565b6040516104999190613db1565b60405180910390f35b6104b56104b0366004613af2565b610996565b6040516104999190613da6565b6104ca6109b4565b60405161049991906145f6565b6104826104e5366004613973565b6109bb565b6104ca610a3b565b6104ca610a40565b6104ca610a47565b610482610510366004613c38565b610a4d565b61051d610ab7565b6040516104999190613cf8565b6104ca610538366004613973565b610ac6565b6104b561054b366004613ab2565b610ad9565b6104ca610b61565b610482610566366004613c38565b610b69565b610482610579366004613af2565b610b9a565b610586610bdf565b604051610499919061460d565b6104826105a1366004613973565b610be8565b6104826105b4366004613c68565b610d3c565b6104b56105c7366004613af2565b610d6b565b610482610db9565b61051d610dcb565b61051d610ddb565b6104ca610dea565b6104826105fa366004613973565b610e8d565b6104ca61110c565b6104ca611113565b61048c61111a565b61051d611137565b6104b5611146565b61051d61114f565b61048261063d366004613c38565b61115f565b6104826111e4565b6104ca610658366004613973565b611226565b61048261066b366004613973565b611241565b6104ca61126b565b6104ca6112a7565b6104ca6112ad565b6104826112b4565b61048261069e366004613c38565b6112c4565b61048261134a565b6104826113bd565b61051d6113f3565b6104826106c9366004613973565b611403565b6104ca61147c565b61048c611483565b6104826106ec366004613973565b6114e4565b6104826106ff366004613973565b611552565b6104b5610712366004613af2565b611684565b6104ca6116ec565b61051d6116f3565b6104b5610735366004613af2565b611703565b610482610748366004613973565b611717565b61048261075b366004613c38565b611741565b61051d6117c7565b6104ca6117d6565b61048261077e366004613c38565b6118e8565b610482610791366004613b72565b611945565b6104ca6107a4366004613973565b6119f2565b6104826107b7366004613973565b611a05565b610482611a2f565b6104826107d2366004613b1c565b611adc565b6104826107e5366004613c38565b611b11565b6104826107f8366004613c38565b611b71565b6104ca61080b36600461398e565b611c50565b610482611c7b565b6104b5611d2a565b6104ca611d39565b610482610836366004613c38565b611d40565b6104ca611d9f565b6104ca611da6565b610482610859366004613973565b611dad565b61048261086c366004613c38565b611e4b565b61048261087f3660046139c2565b611ed1565b6104ca612443565b6104ca61244a565b61051d612451565b6104ca612460565b6104826108b2366004613c38565b612466565b6108bf6124ec565b60ff805460ff60a01b1916600160a01b17905560405133907fd7a915337e28a7bf3a13770590fb6701cbeb9d0f25a71e84d106b10a8e6a4ab190600090a2565b60368054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561098b5780601f106109605761010080835404028352916020019161098b565b820191906000526020600020905b81548152906001019060200180831161096e57829003601f168201915b505050505090505b90565b60006109aa6109a361252c565b8484612530565b5060015b92915050565b6101105481565b6109c3611146565b156109e95760405162461bcd60e51b81526004016109e0906140ac565b60405180910390fd5b6109f16125e4565b60ff80546001600160a01b0319166001600160a01b0383169081179091556040517fcf4ebfb08408f66bc4a7a6945a6842089eeee844a2cc7615e8cf517ce520f3da90600090a250565b60c881565b61010a5481565b60355490565b610a55612623565b60c8811115610a765760405162461bcd60e51b81526004016109e0906144ca565b61010f8190556040517fa254b26086a7ddac6321f8f7b7ae1301e48e0734fc6ad56fb6a4eb58dbd8c49c90610aac9083906145f6565b60405180910390a150565b6066546001600160a01b031681565b6101086020526000908152604090205481565b6000610ae684848461264d565b610b5684610af261252c565b610b51856040518060600160405280602881526020016146f0602891396001600160a01b038a16600090815260346020526040812090610b3061252c565b6001600160a01b031681526020810191909152604001600020549190612762565b612530565b5060015b9392505050565b6301e1855881565b610b71611146565b15610b8e5760405162461bcd60e51b81526004016109e0906140ac565b610b978161278e565b50565b610ba2611146565b15610bbf5760405162461bcd60e51b81526004016109e0906140ac565b604080516000815260208101909152610bdb9083908390612a05565b5050565b60385460ff1690565b610bf0611146565b15610c0d5760405162461bcd60e51b81526004016109e0906140ac565b610c15612623565b6001600160a01b038116610c3b5760405162461bcd60e51b81526004016109e090613fd7565b610100546001600160a01b031615610cf15761010060009054906101000a90046001600160a01b03166001600160a01b031663722713f76040518163ffffffff1660e01b815260040160206040518083038186803b158015610c9c57600080fd5b505afa158015610cb0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd49190613c50565b15610cf15760405162461bcd60e51b81526004016109e090613e83565b61010080546001600160a01b0319166001600160a01b0383169081179091556040517f3412691e1ea2503d6eec15597247048016213c19646b73d4320a20c790b67ee290600090a250565b610d44611146565b15610d615760405162461bcd60e51b81526004016109e0906140ac565b610bdb8282612ac0565b60006109aa610d7861252c565b84610b518560346000610d8961252c565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490612acb565b610dc1612623565b610dc9612af0565b565b610101546001600160a01b031681565b60ff546001600160a01b031681565b6101115460fe546040516370a0823160e01b8152600092610e889261271092610e8292916001600160a01b0316906370a0823190610e2c903090600401613cf8565b60206040518083038186803b158015610e4457600080fd5b505afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c9190613c50565b90612b5e565b90612b98565b905090565b600260cc541415610eb05760405162461bcd60e51b81526004016109e090614522565b600260cc55610ebd612bca565b60fe546001600160a01b0382811691161415610eeb5760405162461bcd60e51b81526004016109e090613fb6565b6040516370a0823160e01b81526000906001600160a01b038316906370a0823190610f1a903090600401613cf8565b60206040518083038186803b158015610f3257600080fd5b505afa158015610f46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f6a9190613c50565b6001600160a01b03831660009081526101086020526040902054909150610f919082612acb565b6001600160a01b03831660009081526101086020908152604080832093909355610109905290812082905561010a54610fcb908390612bf5565b90506000610fdc8361010b54612bf5565b90508115610fff5761010254610fff906001600160a01b03868116911684612c1e565b801561101f5760665461101f906001600160a01b03868116911683612c1e565b6040516370a0823160e01b81526000906001600160a01b038616906370a082319061104e903090600401613cf8565b60206040518083038186803b15801561106657600080fd5b505afa15801561107a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109e9190613c50565b610103549091506110bc906001600160a01b03878116911683612c1e565b43856001600160a01b03167f17cc18c044bdfa5f365fb0f6140ffbaa76843012681aedb2015580693fa49b9483426040516110f89291906145ff565b60405180910390a35050600160cc55505050565b61010b5481565b61010e5481565b604080518082019091526003815262312e3560e81b602082015290565b6065546001600160a01b031681565b609a5460ff1690565b610102546001600160a01b031681565b611167611146565b156111845760405162461bcd60e51b81526004016109e0906140ac565b61118c6125e4565b6127108111156111ae5760405162461bcd60e51b81526004016109e090613f11565b6101118190556040517f5cc7e39e46826190c353c144fe457f6621996ec0f604b3d78e3ac26fd1b4bde290610aac9083906145f6565b6111ec612623565b60ff805460ff60a01b1916905560405133907f136ece421d83ae8c5fe0d9b95b96b35315050bfc3cf21cb5751128f683eb59be90600090a2565b6001600160a01b031660009081526033602052604090205490565b611249612623565b606780546001600160a01b0319166001600160a01b0392909216919091179055565b6000611275610a47565b6112885750670de0b6b3a7640000610993565b610e88611293610a47565b610e82670de0b6b3a7640000610e7c6117d6565b610bb881565b6101065481565b6112bc6124ec565b610dc9612c74565b6112cc611146565b156112e95760405162461bcd60e51b81526004016109e0906140ac565b6112f16125e4565b61010e548111156113145760405162461bcd60e51b81526004016109e090613ffa565b61010a8190556040517f1776ab2b6ca2ecf6879162cd3f7f99594a9d5b67ac64d0d41e63f1e804969ef290610aac9083906145f6565b6113526125e4565b61010060009054906101000a90046001600160a01b03166001600160a01b03166384f227216040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156113a357600080fd5b505af11580156113b7573d6000803e3d6000fd5b50505050565b6113c5611146565b156113e25760405162461bcd60e51b81526004016109e0906140ac565b610dc96113ee33611226565b61278e565b610103546001600160a01b031681565b61140b612623565b6001600160a01b0381166114315760405162461bcd60e51b81526004016109e09061449b565b61010180546001600160a01b0319166001600160a01b0383169081179091556040517f31845eceb9cde510c7e8b37f76301c688feb70bc9653aa4c28a3734999840fd890600090a250565b61010c5481565b60378054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561098b5780601f106109605761010080835404028352916020019161098b565b6114ec6125e4565b6101005460405163283f557960e21b81526001600160a01b039091169063a0fd55e49061151d908490600401613cf8565b600060405180830381600087803b15801561153757600080fd5b505af115801561154b573d6000803e3d6000fd5b5050505050565b61155a6125e4565b60fe546001600160a01b03828116911614156115885760405162461bcd60e51b81526004016109e090613fb6565b61010054604051631bd43be360e01b81526001600160a01b0390911690631bd43be3906115b9908490600401613cf8565b600060405180830381600087803b1580156115d357600080fd5b505af11580156115e7573d6000803e3d6000fd5b50506065546040516370a0823160e01b8152610b9793506001600160a01b039182169250908416906370a0823190611623903090600401613cf8565b60206040518083038186803b15801561163b57600080fd5b505afa15801561164f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116739190613c50565b6001600160a01b0384169190612c1e565b60006109aa61169161252c565b84610b518560405180606001604052806025815260200161471860259139603460006116bb61252c565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190612762565b61010d5481565b610100546001600160a01b031681565b60006109aa61171061252c565b848461264d565b61171f612623565b606580546001600160a01b0319166001600160a01b0392909216919091179055565b611749611146565b156117665760405162461bcd60e51b81526004016109e0906140ac565b61176e6125e4565b61010f548111156117915760405162461bcd60e51b81526004016109e09061419c565b61010c8190556040517f3aa4413905e8f015896ec5880bdde24088ccb19b578f9fcf6800354d5320d4af90610aac9083906145f6565b6067546001600160a01b031681565b6000610e8861010060009054906101000a90046001600160a01b03166001600160a01b031663722713f76040518163ffffffff1660e01b815260040160206040518083038186803b15801561182a57600080fd5b505afa15801561183e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118629190613c50565b60fe546040516370a0823160e01b81526001600160a01b03909116906370a0823190611892903090600401613cf8565b60206040518083038186803b1580156118aa57600080fd5b505afa1580156118be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e29190613c50565b90612acb565b6118f0611146565b1561190d5760405162461bcd60e51b81526004016109e0906140ac565b610b97816000805b5060405190808252806020026020018201604052801561193f578160200160208202803683370190505b50612ac0565b61194d611146565b1561196a5760405162461bcd60e51b81526004016109e0906140ac565b60fe546040516370a0823160e01b8152610b97916001600160a01b0316906370a082319061199c903390600401613cf8565b60206040518083038186803b1580156119b457600080fd5b505afa1580156119c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ec9190613c50565b82612ac0565b6101096020526000908152604090205481565b611a0d612623565b606680546001600160a01b0319166001600160a01b0392909216919091179055565b60ff8054600160a01b90041615611a585760405162461bcd60e51b81526004016109e09061426d565b611a60612ccf565b6000611a6a610dea565b6101005460fe54919250611a8b916001600160a01b03908116911683612c1e565b61010060009054906101000a90046001600160a01b03166001600160a01b031663d389800f6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561153757600080fd5b611ae4611146565b15611b015760405162461bcd60e51b81526004016109e0906140ac565b611b0c838383612a05565b505050565b611b19612623565b610bb8811115611b3b5760405162461bcd60e51b81526004016109e09061420a565b61010e8190556040517fd7fabec26d79f18c91fcbf04b6e1650fcd90cd4f7d6c389feeca8339c012f9bb90610aac9083906145f6565b600260cc541415611b945760405162461bcd60e51b81526004016109e090614522565b600260cc55611ba1612bca565b426000611bb683611bb06117d6565b90612d0e565b9050611bc28383612d36565b6101068390558015611bd957610107819055611be5565b82611be5576000610107555b61010454611bf39084612acb565b6101045561010582905560fe5460405143916001600160a01b0316907fe48bba143e2a0b557fa6f3234bd6ffc704518cc98c7de6a2385549fae27d1b7590611c3e90879042906145ff565b60405180910390a35050600160cc5550565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b611c83611146565b15611ca05760405162461bcd60e51b81526004016109e0906140ac565b60fe546040516370a0823160e01b8152610dc9916001600160a01b0316906370a0823190611cd2903390600401613cf8565b60206040518083038186803b158015611cea57600080fd5b505afa158015611cfe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d229190613c50565b600080611915565b60ff8054600160a01b90041681565b6101075481565b611d48612623565b60c8811115611d695760405162461bcd60e51b81526004016109e0906142fa565b6101108190556040517f4c7b8194b874abd9829fc99a7fd17528dd31a043b15b067e806b9aed5e2febb390610aac9083906145f6565b61010f5481565b6101055481565b611db5611146565b15611dd25760405162461bcd60e51b81526004016109e0906140ac565b611dda612623565b6001600160a01b038116611e005760405162461bcd60e51b81526004016109e090613fd7565b61010280546001600160a01b0319166001600160a01b0383169081179091556040517fcb7ef3e545f5cdb893f5c568ba710fe08f336375a2d9fd66e161033f8fc09ef390600090a250565b611e53611146565b15611e705760405162461bcd60e51b81526004016109e0906140ac565b611e786125e4565b61010e54811115611e9b5760405162461bcd60e51b81526004016109e090614559565b61010b8190556040517fa2b496c086c66c1966a950920059fb82fdb25b562982c79b2aa490fde65f647b90610aac9083906145f6565b600054610100900460ff1680611eea5750611eea612e23565b80611ef8575060005460ff16155b611f145760405162461bcd60e51b81526004016109e09061410d565b600054610100900460ff16158015611f3f576000805460ff1961ff0019909116610100171660011790555b611f47611146565b15611f645760405162461bcd60e51b81526004016109e0906140ac565b6001600160a01b038b16611f7757600080fd5b6001600160a01b038a16611f8a57600080fd5b6001600160a01b038916611f9d57600080fd5b6001600160a01b038816611fb057600080fd5b6001600160a01b038716611fc357600080fd5b6001600160a01b038616611fd657600080fd5b6001600160a01b038516611fe957600080fd5b8151610bb8101561200c5760405162461bcd60e51b81526004016109e09061436f565b6020820151610bb810156120325760405162461bcd60e51b81526004016109e09061420a565b604082015160c810156120575760405162461bcd60e51b81526004016109e0906144ca565b606082015160c8101561207c5760405162461bcd60e51b81526004016109e0906142fa565b60608060008d90507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470876040516020016120b69190613cad565b60405160208183030381529060405280519060200120146120d957869250612196565b6040518060400160405280600c81526020016b02130b233b2b91029b2ba3a160a51b815250816001600160a01b03166306fdde036040518163ffffffff1660e01b815260040160006040518083038186803b15801561213757600080fd5b505afa15801561214b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526121739190810190613bc5565b604051602001612184929190613cc9565b60405160208183030381529060405292505b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470866040516020016121c89190613cad565b60405160208183030381529060405280519060200120146121eb5785915061229d565b604051806040016040528060018152602001603160f91b815250816001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801561223e57600080fd5b505afa158015612252573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261227a9190810190613bc5565b60405160200161228b929190613cc9565b60405160208183030381529060405291505b6122a78383612e34565b6122af612eca565b6122b7612f5c565b8d60fe60006101000a8154816001600160a01b0302191690836001600160a01b031602179055508c606560006101000a8154816001600160a01b0302191690836001600160a01b031602179055508961010260006101000a8154816001600160a01b0302191690836001600160a01b0316021790555088606660006101000a8154816001600160a01b0302191690836001600160a01b031602179055508b606760006101000a8154816001600160a01b0302191690836001600160a01b031602179055508a61010160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508761010360006101000a8154816001600160a01b0302191690836001600160a01b031602179055504261010581905550846000600481106123e057fe5b6020908102919091015161010a5585015161010b55505050604082015161010c55606082015161010d55610bb861010e5560c861010f8190556101105561251c610111558015612436576000805461ff00191690555b5050505050505050505050565b6101045481565b6101115481565b60fe546001600160a01b031681565b61271081565b61246e611146565b1561248b5760405162461bcd60e51b81526004016109e0906140ac565b6124936125e4565b610110548111156124b65760405162461bcd60e51b81526004016109e090613f48565b61010d8190556040517fd87632b1c6ebfa21acbca0e3279b3cf6385a377cb8fda51e5b866baa6e6012ab90610aac9083906145f6565b610101546001600160a01b031633148061251057506065546001600160a01b031633145b610dc95760405162461bcd60e51b81526004016109e0906142d5565b3390565b6001600160a01b0383166125565760405162461bcd60e51b81526004016109e0906143b0565b6001600160a01b03821661257c5760405162461bcd60e51b81526004016109e090613ecf565b6001600160a01b0380841660008181526034602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906125d79085906145f6565b60405180910390a3505050565b6066546001600160a01b031633148061260757506065546001600160a01b031633145b610dc95760405162461bcd60e51b81526004016109e0906140d6565b6065546001600160a01b03163314610dc95760405162461bcd60e51b81526004016109e0906144fa565b6001600160a01b0383166126735760405162461bcd60e51b81526004016109e09061432a565b6001600160a01b0382166126995760405162461bcd60e51b81526004016109e090613e12565b6126a4838383611b0c565b6126e1816040518060600160405280602681526020016146ca602691396001600160a01b0386166000908152603360205260409020549190612762565b6001600160a01b0380851660009081526033602052604080822093909355908416815220546127109082612acb565b6001600160a01b0380841660008181526033602052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906125d79085906145f6565b600081848411156127865760405162461bcd60e51b81526004016109e09190613db1565b505050900390565b600260cc5414156127b15760405162461bcd60e51b81526004016109e090614522565b600260cc55806127d35760405162461bcd60e51b81526004016109e09061424b565b60006127ec6127e0610a47565b610e8284610e7c6117d6565b90506127f83383612fd2565b60fe546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612829903090600401613cf8565b60206040518083038186803b15801561284157600080fd5b505afa158015612855573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128799190613c50565b90508181101561299f57600061288f8383612d0e565b61010054604051632e1a7d4d60e01b81529192506001600160a01b031690632e1a7d4d906128c19084906004016145f6565b600060405180830381600087803b1580156128db57600080fd5b505af11580156128ef573d6000803e3d6000fd5b505060fe546040516370a0823160e01b8152600093506001600160a01b0390911691506370a0823190612926903090600401613cf8565b60206040518083038186803b15801561293e57600080fd5b505afa158015612952573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129769190613c50565b905060006129848285612d0e565b90508281101561299b576129988482612acb565b94505b5050505b60006129ae8361010c54612bf5565b90506129d1336129be8584612d0e565b60fe546001600160a01b03169190612c1e565b80156129fa57610102546129fa906001600160a01b0316826129f581611bb06117d6565b6130b4565b5050600160cc555050565b60ff546001600160a01b031615612ab65760ff54604051631a9ee26f60e01b81526001600160a01b0390911690631a9ee26f90612a4a90869086908690600401613d49565b60206040518083038186803b158015612a6257600080fd5b505afa158015612a76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a9a9190613ba5565b612ab65760405162461bcd60e51b81526004016109e0906141d3565b611b0c83836130f2565b610bdb338383612a05565b600082820183811015610b5a5760405162461bcd60e51b81526004016109e090613f7f565b612af8611146565b612b145760405162461bcd60e51b81526004016109e090613e55565b609a805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612b4761252c565b604051612b549190613cf8565b60405180910390a1565b600082612b6d575060006109ae565b82820282848281612b7a57fe5b0414610b5a5760405162461bcd60e51b81526004016109e09061415b565b6000808211612bb95760405162461bcd60e51b81526004016109e090614075565b818381612bc257fe5b049392505050565b610100546001600160a01b03163314610dc95760405162461bcd60e51b81526004016109e09061442b565b600081612c04575060006109ae565b6000612c16612710610e828686612b5e565b949350505050565b611b0c8363a9059cbb60e01b8484604051602401612c3d929190613d30565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526132d4565b612c7c611146565b15612c995760405162461bcd60e51b81526004016109e0906140ac565b609a805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612b4761252c565b6067546001600160a01b0316331480612cf257506065546001600160a01b031633145b610dc95760405162461bcd60e51b81526004016109e090613de4565b600082821115612d305760405162461bcd60e51b81526004016109e09061403e565b50900390565b600080612d4284613363565b915091506000612d5e6101055485612d0e90919063ffffffff16565b905060008061010d5411612d73576000612d9e565b612d9e612710610e826301e18558610e8286610e7c612d948d611bb06117d6565b61010d5490612b5e565b90506000612dac8583612acb565b90506000612dc085611bb084611bb06117d6565b90508115612de05761010254612de0906001600160a01b031683836130b4565b8415801590612df957506066546001600160a01b031615155b15612e1957606654612e19906001600160a01b0316866129f58486612acb565b5050505050505050565b6000612e2e30613392565b15905090565b600054610100900460ff1680612e4d5750612e4d612e23565b80612e5b575060005460ff16155b612e775760405162461bcd60e51b81526004016109e09061410d565b600054610100900460ff16158015612ea2576000805460ff1961ff0019909116610100171660011790555b612eaa613398565b612eb48383613419565b8015611b0c576000805461ff0019169055505050565b600054610100900460ff1680612ee35750612ee3612e23565b80612ef1575060005460ff16155b612f0d5760405162461bcd60e51b81526004016109e09061410d565b600054610100900460ff16158015612f38576000805460ff1961ff0019909116610100171660011790555b612f40613398565b612f486134d2565b8015610b97576000805461ff001916905550565b600054610100900460ff1680612f755750612f75612e23565b80612f83575060005460ff16155b612f9f5760405162461bcd60e51b81526004016109e09061410d565b600054610100900460ff16158015612fca576000805460ff1961ff0019909116610100171660011790555b612f4861355e565b6001600160a01b038216612ff85760405162461bcd60e51b81526004016109e090614294565b61300482600083611b0c565b613041816040518060600160405280602281526020016146a8602291396001600160a01b0385166000908152603360205260409020549190612762565b6001600160a01b0383166000908152603360205260409020556035546130679082612d0e565b6035556040516000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906130a89085906145f6565b60405180910390a35050565b60006130be610a47565b6130c95750816130e2565b6130df82610e826130d8610a47565b8690612b5e565b90505b80156113b7576113b784826135e5565b600260cc5414156131155760405162461bcd60e51b81526004016109e090614522565b600260cc556001600160a01b0382166131405760405162461bcd60e51b81526004016109e090613fd7565b8061315d5760405162461bcd60e51b81526004016109e09061459d565b60ff8054600160a01b900416156131865760405162461bcd60e51b81526004016109e09061426d565b60006131906117d6565b60fe546040516370a0823160e01b81529192506000916001600160a01b03909116906370a08231906131c6903090600401613cf8565b60206040518083038186803b1580156131de57600080fd5b505afa1580156131f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132169190613c50565b60fe54909150613231906001600160a01b0316333086613699565b60fe546040516370a0823160e01b81526000916001600160a01b0316906370a0823190613262903090600401613cf8565b60206040518083038186803b15801561327a57600080fd5b505afa15801561328e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132b29190613c50565b90506132c8856132c28385612d0e565b856130b4565b5050600160cc55505050565b6060613329826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166136ba9092919063ffffffff16565b805190915015611b0c57808060200190518101906133479190613ba5565b611b0c5760405162461bcd60e51b81526004016109e090614451565b60008060006133758461010a54612bf5565b905060006133868561010b54612bf5565b91935090915050915091565b3b151590565b600054610100900460ff16806133b157506133b1612e23565b806133bf575060005460ff16155b6133db5760405162461bcd60e51b81526004016109e09061410d565b600054610100900460ff16158015612f48576000805460ff1961ff0019909116610100171660011790558015610b97576000805461ff001916905550565b600054610100900460ff16806134325750613432612e23565b80613440575060005460ff16155b61345c5760405162461bcd60e51b81526004016109e09061410d565b600054610100900460ff16158015613487576000805460ff1961ff0019909116610100171660011790555b825161349a90603690602086019061379d565b5081516134ae90603790602085019061379d565b506038805460ff191660121790558015611b0c576000805461ff0019169055505050565b600054610100900460ff16806134eb57506134eb612e23565b806134f9575060005460ff16155b6135155760405162461bcd60e51b81526004016109e09061410d565b600054610100900460ff16158015613540576000805460ff1961ff0019909116610100171660011790555b609a805460ff191690558015610b97576000805461ff001916905550565b600054610100900460ff16806135775750613577612e23565b80613585575060005460ff16155b6135a15760405162461bcd60e51b81526004016109e09061410d565b600054610100900460ff161580156135cc576000805460ff1961ff0019909116610100171660011790555b600160cc558015610b97576000805461ff001916905550565b6001600160a01b03821661360b5760405162461bcd60e51b81526004016109e0906145bf565b61361760008383611b0c565b6035546136249082612acb565b6035556001600160a01b03821660009081526033602052604090205461364a9082612acb565b6001600160a01b0383166000818152603360205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906130a89085906145f6565b6113b7846323b872dd60e01b858585604051602401612c3d93929190613d0c565b6060612c168484600085856136ce85613392565b6136ea5760405162461bcd60e51b81526004016109e0906143f4565b60006060866001600160a01b031685876040516137079190613cad565b60006040518083038185875af1925050503d8060008114613744576040519150601f19603f3d011682016040523d82523d6000602084013e613749565b606091505b5091509150613759828286613764565b979650505050505050565b60608315613773575081610b5a565b8251156137835782518084602001fd5b8160405162461bcd60e51b81526004016109e09190613db1565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106137de57805160ff191683800117855561380b565b8280016001018555821561380b579182015b8281111561380b5782518255916020019190600101906137f0565b5061381792915061381b565b5090565b5b80821115613817576000815560010161381c565b80356001600160a01b03811681146109ae57600080fd5b600082601f830112613857578081fd5b813567ffffffffffffffff81111561386d578182fd5b602080820261387d82820161461b565b8381529350818401858301828701840188101561389957600080fd5b600092505b848310156138bc57803582526001929092019190830190830161389e565b505050505092915050565b600082601f8301126138d7578081fd5b6138e1608061461b565b90508082846080850111156138f557600080fd5b60005b60048110156139175781358352602092830192909101906001016138f8565b50505092915050565b600082601f830112613930578081fd5b813561394361393e82614642565b61461b565b915080825283602082850101111561395a57600080fd5b8060208401602084013760009082016020015292915050565b600060208284031215613984578081fd5b610b5a8383613830565b600080604083850312156139a0578081fd5b6139aa8484613830565b91506139b98460208501613830565b90509250929050565b6000806000806000806000806000806101a08b8d0312156139e1578586fd5b6139eb8c8c613830565b99506139fa8c60208d01613830565b9850613a098c60408d01613830565b9750613a188c60608d01613830565b9650613a278c60808d01613830565b9550613a368c60a08d01613830565b9450613a458c60c08d01613830565b935060e08b013567ffffffffffffffff80821115613a61578485fd5b613a6d8e838f01613920565b94506101008d0135915080821115613a83578384fd5b50613a908d828e01613920565b925050613aa18c6101208d016138c7565b90509295989b9194979a5092959850565b600080600060608486031215613ac6578283fd5b8335613ad181614692565b92506020840135613ae181614692565b929592945050506040919091013590565b60008060408385031215613b04578182fd5b613b0e8484613830565b946020939093013593505050565b600080600060608486031215613b30578283fd5b613b3a8585613830565b925060208401359150604084013567ffffffffffffffff811115613b5c578182fd5b613b6886828701613847565b9150509250925092565b600060208284031215613b83578081fd5b813567ffffffffffffffff811115613b99578182fd5b612c1684828501613847565b600060208284031215613bb6578081fd5b81518015158114610b5a578182fd5b600060208284031215613bd6578081fd5b815167ffffffffffffffff811115613bec578182fd5b8201601f81018413613bfc578182fd5b8051613c0a61393e82614642565b818152856020838501011115613c1e578384fd5b613c2f826020830160208601614666565b95945050505050565b600060208284031215613c49578081fd5b5035919050565b600060208284031215613c61578081fd5b5051919050565b60008060408385031215613c7a578081fd5b82359150602083013567ffffffffffffffff811115613c97578182fd5b613ca385828601613847565b9150509250929050565b60008251613cbf818460208701614666565b9190910192915050565b60008351613cdb818460208801614666565b835190830190613cef818360208801614666565b01949350505050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b038416815260208082018490526060604083018190528351908301819052600091848101916080850190845b81811015613d9857845183529383019391830191600101613d7c565b509098975050505050505050565b901515815260200190565b6000602082528251806020840152613dd0816040850160208701614666565b601f01601f19169190910160400192915050565b6020808252601490820152736f6e6c79417574686f72697a65644163746f727360601b604082015260600190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526014908201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604082015260600190565b6020808252602c908201527f506c65617365207769746864726177546f5661756c74206265666f726520636860408201526b185b99da5b99c81cdd1c985d60a21b606082015260800190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252601e908201527f746f4561726e4270732073686f756c64206265203c3d204d41585f4250530000604082015260600190565b60208082526018908201527f457863657373697665206d616e6167656d656e74206665650000000000000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b602080825260079082015266139bc81dd85b9d60ca1b604082015260600190565b60208082526009908201526804164647265737320360bc1b604082015260600190565b60208082526024908201527f45786365737369766520676f7665726e616e636520706572666f726d616e63656040820152632066656560e01b606082015260800190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252601a908201527f6f6e6c79476f7665726e616e63654f7253747261746567697374000000000000604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526018908201527f457863657373697665207769746864726177616c206665650000000000000000604082015260600190565b60208082526019908201527f47756573744c6973743a204e6f7420417574686f72697a656400000000000000604082015260600190565b60208082526021908201527f706572666f726d616e63654665655374726174656769737420746f6f206869676040820152600d60fb1b606082015260800190565b602080825260089082015267302053686172657360c01b604082015260600190565b6020808252600d908201526c1c185d5cd95911195c1bdcda5d609a1b604082015260600190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b6020808252600b908201526a6f6e6c795061757365727360a81b604082015260600190565b6020808252601690820152750dac2dcc2cecadacadce88ccaca40e8dede40d0d2ced60531b604082015260600190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526021908201527f706572666f726d616e6365466565476f7665726e616e636520746f6f206869676040820152600d60fb1b606082015260800190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600c908201526b6f6e6c79537472617465677960a01b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252601590820152740416464726573732063616e6e6f742062652030783605c1b604082015260600190565b6020808252601690820152750eed2e8d0c8e4c2eec2d88ccaca40e8dede40d0d2ced60531b604082015260600190565b6020808252600e908201526d6f6e6c79476f7665726e616e636560901b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60208082526024908201527f457863657373697665207374726174656769737420706572666f726d616e63656040820152632066656560e01b606082015260800190565b6020808252600890820152670416d6f756e7420360c41b604082015260600190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b90815260200190565b918252602082015260400190565b60ff91909116815260200190565b60405181810167ffffffffffffffff8111828210171561463a57600080fd5b604052919050565b600067ffffffffffffffff821115614658578081fd5b50601f01601f191660200190565b60005b83811015614681578181015183820152602001614669565b838111156113b75750506000910152565b6001600160a01b0381168114610b9757600080fdfe45524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212200a6ce01bfd967533edb93dde951933f743c58cb33e26e1409a62d09c14bb151d64736f6c634300060c0033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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