Overview
ETH Balance
0 ETH
Eth Value
$0.00Token Holdings
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 5 from a total of 5 transactions
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
20125559 | 105 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
SingleSidedPTcore
Compiler Version
v0.8.18+commit.87f61d96
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2024-06-19 */ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.18; // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol) // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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); /** * @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 `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount) external returns (bool); } // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); } // OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.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 meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } } /** * @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.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override 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 default value returned by this function, unless * it's overridden. * * 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 override returns (uint8) { return 18; } /** * @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: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, 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}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, 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}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); 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) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + 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) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `from` to `to`. * * This 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: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer(address from, address to, uint256 amount) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by // decrementing then incrementing. _balances[to] += amount; } emit Transfer(from, to, amount); _afterTokenTransfer(from, to, 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: * * - `account` 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 += amount; unchecked { // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. _balances[account] += amount; } emit Transfer(address(0), account, amount); _afterTokenTransfer(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); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; // Overflow not possible: amount <= accountBalance <= totalSupply. _totalSupply -= amount; } emit Transfer(account, address(0), amount); _afterTokenTransfer(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 Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @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 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 {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been 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 _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {} } // TokenizedStrategy interface used for internal view delegateCalls. // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC4626.sol) /** * @dev Interface of the ERC4626 "Tokenized Vault Standard", as defined in * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626]. * * _Available since v4.7._ */ interface IERC4626 is IERC20, IERC20Metadata { event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares); event Withdraw( address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares ); /** * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing. * * - MUST be an ERC-20 token contract. * - MUST NOT revert. */ function asset() external view returns (address assetTokenAddress); /** * @dev Returns the total amount of the underlying asset that is “managed” by Vault. * * - SHOULD include any compounding that occurs from yield. * - MUST be inclusive of any fees that are charged against assets in the Vault. * - MUST NOT revert. */ function totalAssets() external view returns (uint256 totalManagedAssets); /** * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal * scenario where all the conditions are met. * * - MUST NOT be inclusive of any fees that are charged against assets in the Vault. * - MUST NOT show any variations depending on the caller. * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. * - MUST NOT revert. * * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and * from. */ function convertToShares(uint256 assets) external view returns (uint256 shares); /** * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal * scenario where all the conditions are met. * * - MUST NOT be inclusive of any fees that are charged against assets in the Vault. * - MUST NOT show any variations depending on the caller. * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. * - MUST NOT revert. * * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and * from. */ function convertToAssets(uint256 shares) external view returns (uint256 assets); /** * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver, * through a deposit call. * * - MUST return a limited value if receiver is subject to some deposit limit. * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited. * - MUST NOT revert. */ function maxDeposit(address receiver) external view returns (uint256 maxAssets); /** * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given * current on-chain conditions. * * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit * call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called * in the same transaction. * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the * deposit would be accepted, regardless if the user has enough tokens approved, etc. * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees. * - MUST NOT revert. * * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in * share price or some other type of condition, meaning the depositor will lose assets by depositing. */ function previewDeposit(uint256 assets) external view returns (uint256 shares); /** * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens. * * - MUST emit the Deposit event. * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the * deposit execution, and are accounted for during deposit. * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not * approving enough underlying tokens to the Vault contract, etc). * * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token. */ function deposit(uint256 assets, address receiver) external returns (uint256 shares); /** * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call. * - MUST return a limited value if receiver is subject to some mint limit. * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted. * - MUST NOT revert. */ function maxMint(address receiver) external view returns (uint256 maxShares); /** * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given * current on-chain conditions. * * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call * in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the * same transaction. * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint * would be accepted, regardless if the user has enough tokens approved, etc. * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees. * - MUST NOT revert. * * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in * share price or some other type of condition, meaning the depositor will lose assets by minting. */ function previewMint(uint256 shares) external view returns (uint256 assets); /** * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens. * * - MUST emit the Deposit event. * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint * execution, and are accounted for during mint. * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not * approving enough underlying tokens to the Vault contract, etc). * * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token. */ function mint(uint256 shares, address receiver) external returns (uint256 assets); /** * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the * Vault, through a withdraw call. * * - MUST return a limited value if owner is subject to some withdrawal limit or timelock. * - MUST NOT revert. */ function maxWithdraw(address owner) external view returns (uint256 maxAssets); /** * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block, * given current on-chain conditions. * * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw * call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if * called * in the same transaction. * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though * the withdrawal would be accepted, regardless if the user has enough shares, etc. * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees. * - MUST NOT revert. * * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in * share price or some other type of condition, meaning the depositor will lose assets by depositing. */ function previewWithdraw(uint256 assets) external view returns (uint256 shares); /** * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver. * * - MUST emit the Withdraw event. * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the * withdraw execution, and are accounted for during withdraw. * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner * not having enough shares, etc). * * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed. * Those methods should be performed separately. */ function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares); /** * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault, * through a redeem call. * * - MUST return a limited value if owner is subject to some withdrawal limit or timelock. * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock. * - MUST NOT revert. */ function maxRedeem(address owner) external view returns (uint256 maxShares); /** * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block, * given current on-chain conditions. * * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call * in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the * same transaction. * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the * redemption would be accepted, regardless if the user has enough shares, etc. * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees. * - MUST NOT revert. * * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in * share price or some other type of condition, meaning the depositor will lose assets by redeeming. */ function previewRedeem(uint256 shares) external view returns (uint256 assets); /** * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver. * * - MUST emit the Withdraw event. * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the * redeem execution, and are accounted for during redeem. * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner * not having enough shares, etc). * * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed. * Those methods should be performed separately. */ function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets); } // OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol) /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); } // Interface that implements the 4626 standard and the implementation functions interface ITokenizedStrategy is IERC4626, IERC20Permit { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event StrategyShutdown(); event NewTokenizedStrategy( address indexed strategy, address indexed asset, string apiVersion ); event Reported( uint256 profit, uint256 loss, uint256 protocolFees, uint256 performanceFees ); event UpdatePerformanceFeeRecipient( address indexed newPerformanceFeeRecipient ); event UpdateKeeper(address indexed newKeeper); event UpdatePerformanceFee(uint16 newPerformanceFee); event UpdateManagement(address indexed newManagement); event UpdateEmergencyAdmin(address indexed newEmergencyAdmin); event UpdateProfitMaxUnlockTime(uint256 newProfitMaxUnlockTime); event UpdatePendingManagement(address indexed newPendingManagement); /*////////////////////////////////////////////////////////////// INITIALIZATION //////////////////////////////////////////////////////////////*/ function initialize( address _asset, string memory _name, address _management, address _performanceFeeRecipient, address _keeper ) external; /*////////////////////////////////////////////////////////////// NON-STANDARD 4626 OPTIONS //////////////////////////////////////////////////////////////*/ function withdraw( uint256 assets, address receiver, address owner, uint256 maxLoss ) external returns (uint256); function redeem( uint256 shares, address receiver, address owner, uint256 maxLoss ) external returns (uint256); /*////////////////////////////////////////////////////////////// MODIFIER HELPERS //////////////////////////////////////////////////////////////*/ function requireManagement(address _sender) external view; function requireKeeperOrManagement(address _sender) external view; function requireEmergencyAuthorized(address _sender) external view; /*////////////////////////////////////////////////////////////// KEEPERS FUNCTIONS //////////////////////////////////////////////////////////////*/ function tend() external; function report() external returns (uint256 _profit, uint256 _loss); /*////////////////////////////////////////////////////////////// CONSTANTS //////////////////////////////////////////////////////////////*/ function MAX_FEE() external view returns (uint16); function FACTORY() external view returns (address); /*////////////////////////////////////////////////////////////// GETTERS //////////////////////////////////////////////////////////////*/ function apiVersion() external view returns (string memory); function pricePerShare() external view returns (uint256); function management() external view returns (address); function pendingManagement() external view returns (address); function keeper() external view returns (address); function emergencyAdmin() external view returns (address); function performanceFee() external view returns (uint16); function performanceFeeRecipient() external view returns (address); function fullProfitUnlockDate() external view returns (uint256); function profitUnlockingRate() external view returns (uint256); function profitMaxUnlockTime() external view returns (uint256); function lastReport() external view returns (uint256); function isShutdown() external view returns (bool); function unlockedShares() external view returns (uint256); /*////////////////////////////////////////////////////////////// SETTERS //////////////////////////////////////////////////////////////*/ function setPendingManagement(address) external; function acceptManagement() external; function setKeeper(address _keeper) external; function setEmergencyAdmin(address _emergencyAdmin) external; function setPerformanceFee(uint16 _performanceFee) external; function setPerformanceFeeRecipient( address _performanceFeeRecipient ) external; function setProfitMaxUnlockTime(uint256 _profitMaxUnlockTime) external; function shutdownStrategy() external; function emergencyWithdraw(uint256 _amount) external; } /** * @title YearnV3 Base Strategy * @author yearn.finance * @notice * BaseStrategy implements all of the required functionality to * seamlessly integrate with the `TokenizedStrategy` implementation contract * allowing anyone to easily build a fully permissionless ERC-4626 compliant * Vault by inheriting this contract and overriding three simple functions. * It utilizes an immutable proxy pattern that allows the BaseStrategy * to remain simple and small. All standard logic is held within the * `TokenizedStrategy` and is reused over any n strategies all using the * `fallback` function to delegatecall the implementation so that strategists * can only be concerned with writing their strategy specific code. * * This contract should be inherited and the three main abstract methods * `_deployFunds`, `_freeFunds` and `_harvestAndReport` implemented to adapt * the Strategy to the particular needs it has to generate yield. There are * other optional methods that can be implemented to further customize * the strategy if desired. * * All default storage for the strategy is controlled and updated by the * `TokenizedStrategy`. The implementation holds a storage struct that * contains all needed global variables in a manual storage slot. This * means strategists can feel free to implement their own custom storage * variables as they need with no concern of collisions. All global variables * can be viewed within the Strategy by a simple call using the * `TokenizedStrategy` variable. IE: TokenizedStrategy.globalVariable();. */ abstract contract BaseStrategy { /*////////////////////////////////////////////////////////////// MODIFIERS //////////////////////////////////////////////////////////////*/ /** * @dev Used on TokenizedStrategy callback functions to make sure it is post * a delegateCall from this address to the TokenizedStrategy. */ modifier onlySelf() { _onlySelf(); _; } /** * @dev Use to assure that the call is coming from the strategies management. */ modifier onlyManagement() { TokenizedStrategy.requireManagement(msg.sender); _; } /** * @dev Use to assure that the call is coming from either the strategies * management or the keeper. */ modifier onlyKeepers() { TokenizedStrategy.requireKeeperOrManagement(msg.sender); _; } /** * @dev Use to assure that the call is coming from either the strategies * management or the emergency admin. */ modifier onlyEmergencyAuthorized() { TokenizedStrategy.requireEmergencyAuthorized(msg.sender); _; } /** * @dev Require that the msg.sender is this address. */ function _onlySelf() internal view { require(msg.sender == address(this), "!self"); } /*////////////////////////////////////////////////////////////// CONSTANTS //////////////////////////////////////////////////////////////*/ /** * @dev This is the address of the TokenizedStrategy implementation * contract that will be used by all strategies to handle the * accounting, logic, storage etc. * * Any external calls to the that don't hit one of the functions * defined in this base or the strategy will end up being forwarded * through the fallback function, which will delegateCall this address. * * This address should be the same for every strategy, never be adjusted * and always be checked before any integration with the Strategy. */ address public constant tokenizedStrategyAddress = 0xBB51273D6c746910C7C06fe718f30c936170feD0; /*////////////////////////////////////////////////////////////// IMMUTABLES //////////////////////////////////////////////////////////////*/ /** * @dev Underlying asset the Strategy is earning yield on. * Stored here for cheap retrievals within the strategy. */ ERC20 internal immutable asset; /** * @dev This variable is set to address(this) during initialization of each strategy. * * This can be used to retrieve storage data within the strategy * contract as if it were a linked library. * * i.e. uint256 totalAssets = TokenizedStrategy.totalAssets() * * Using address(this) will mean any calls using this variable will lead * to a call to itself. Which will hit the fallback function and * delegateCall that to the actual TokenizedStrategy. */ ITokenizedStrategy internal immutable TokenizedStrategy; /** * @notice Used to initialize the strategy on deployment. * * This will set the `TokenizedStrategy` variable for easy * internal view calls to the implementation. As well as * initializing the default storage variables based on the * parameters and using the deployer for the permissioned roles. * * @param _asset Address of the underlying asset. * @param _name Name the strategy will use. */ constructor(address _asset, string memory _name) { asset = ERC20(_asset); // Set instance of the implementation for internal use. TokenizedStrategy = ITokenizedStrategy(address(this)); // Initialize the strategy's storage variables. _delegateCall( abi.encodeCall( ITokenizedStrategy.initialize, (_asset, _name, msg.sender, msg.sender, msg.sender) ) ); // Store the tokenizedStrategyAddress at the standard implementation // address storage slot so etherscan picks up the interface. This gets // stored on initialization and never updated. assembly { sstore( // keccak256('eip1967.proxy.implementation' - 1) 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc, tokenizedStrategyAddress ) } } /*////////////////////////////////////////////////////////////// NEEDED TO BE OVERRIDDEN BY STRATEGIST //////////////////////////////////////////////////////////////*/ /** * @dev Can deploy up to '_amount' of 'asset' in the yield source. * * This function is called at the end of a {deposit} or {mint} * call. Meaning that unless a whitelist is implemented it will * be entirely permissionless and thus can be sandwiched or otherwise * manipulated. * * @param _amount The amount of 'asset' that the strategy can attempt * to deposit in the yield source. */ function _deployFunds(uint256 _amount) internal virtual; /** * @dev Should attempt to free the '_amount' of 'asset'. * * NOTE: The amount of 'asset' that is already loose has already * been accounted for. * * This function is called during {withdraw} and {redeem} calls. * Meaning that unless a whitelist is implemented it will be * entirely permissionless and thus can be sandwiched or otherwise * manipulated. * * Should not rely on asset.balanceOf(address(this)) calls other than * for diff accounting purposes. * * Any difference between `_amount` and what is actually freed will be * counted as a loss and passed on to the withdrawer. This means * care should be taken in times of illiquidity. It may be better to revert * if withdraws are simply illiquid so not to realize incorrect losses. * * @param _amount, The amount of 'asset' to be freed. */ function _freeFunds(uint256 _amount) internal virtual; /** * @dev Internal function to harvest all rewards, redeploy any idle * funds and return an accurate accounting of all funds currently * held by the Strategy. * * This should do any needed harvesting, rewards selling, accrual, * redepositing etc. to get the most accurate view of current assets. * * NOTE: All applicable assets including loose assets should be * accounted for in this function. * * Care should be taken when relying on oracles or swap values rather * than actual amounts as all Strategy profit/loss accounting will * be done based on this returned value. * * This can still be called post a shutdown, a strategist can check * `TokenizedStrategy.isShutdown()` to decide if funds should be * redeployed or simply realize any profits/losses. * * @return _totalAssets A trusted and accurate account for the total * amount of 'asset' the strategy currently holds including idle funds. */ function _harvestAndReport() internal virtual returns (uint256 _totalAssets); /*////////////////////////////////////////////////////////////// OPTIONAL TO OVERRIDE BY STRATEGIST //////////////////////////////////////////////////////////////*/ /** * @dev Optional function for strategist to override that can * be called in between reports. * * If '_tend' is used tendTrigger() will also need to be overridden. * * This call can only be called by a permissioned role so may be * through protected relays. * * This can be used to harvest and compound rewards, deposit idle funds, * perform needed position maintenance or anything else that doesn't need * a full report for. * * EX: A strategy that can not deposit funds without getting * sandwiched can use the tend when a certain threshold * of idle to totalAssets has been reached. * * This will have no effect on PPS of the strategy till report() is called. * * @param _totalIdle The current amount of idle funds that are available to deploy. */ function _tend(uint256 _totalIdle) internal virtual {} /** * @dev Optional trigger to override if tend() will be used by the strategy. * This must be implemented if the strategy hopes to invoke _tend(). * * @return . Should return true if tend() should be called by keeper or false if not. */ function _tendTrigger() internal view virtual returns (bool) { return false; } /** * @notice Returns if tend() should be called by a keeper. * * @return . Should return true if tend() should be called by keeper or false if not. * @return . Calldata for the tend call. */ function tendTrigger() external view virtual returns (bool, bytes memory) { return ( // Return the status of the tend trigger. _tendTrigger(), // And the needed calldata either way. abi.encodeWithSelector(ITokenizedStrategy.tend.selector) ); } /** * @notice Gets the max amount of `asset` that an address can deposit. * @dev Defaults to an unlimited amount for any address. But can * be overridden by strategists. * * This function will be called before any deposit or mints to enforce * any limits desired by the strategist. This can be used for either a * traditional deposit limit or for implementing a whitelist etc. * * EX: * if(isAllowed[_owner]) return super.availableDepositLimit(_owner); * * This does not need to take into account any conversion rates * from shares to assets. But should know that any non max uint256 * amounts may be converted to shares. So it is recommended to keep * custom amounts low enough as not to cause overflow when multiplied * by `totalSupply`. * * @param . The address that is depositing into the strategy. * @return . The available amount the `_owner` can deposit in terms of `asset` */ function availableDepositLimit( address /*_owner*/ ) public view virtual returns (uint256) { return type(uint256).max; } /** * @notice Gets the max amount of `asset` that can be withdrawn. * @dev Defaults to an unlimited amount for any address. But can * be overridden by strategists. * * This function will be called before any withdraw or redeem to enforce * any limits desired by the strategist. This can be used for illiquid * or sandwichable strategies. It should never be lower than `totalIdle`. * * EX: * return TokenIzedStrategy.totalIdle(); * * This does not need to take into account the `_owner`'s share balance * or conversion rates from shares to assets. * * @param . The address that is withdrawing from the strategy. * @return . The available amount that can be withdrawn in terms of `asset` */ function availableWithdrawLimit( address /*_owner*/ ) public view virtual returns (uint256) { return type(uint256).max; } /** * @dev Optional function for a strategist to override that will * allow management to manually withdraw deployed funds from the * yield source if a strategy is shutdown. * * This should attempt to free `_amount`, noting that `_amount` may * be more than is currently deployed. * * NOTE: This will not realize any profits or losses. A separate * {report} will be needed in order to record any profit/loss. If * a report may need to be called after a shutdown it is important * to check if the strategy is shutdown during {_harvestAndReport} * so that it does not simply re-deploy all funds that had been freed. * * EX: * if(freeAsset > 0 && !TokenizedStrategy.isShutdown()) { * depositFunds... * } * * @param _amount The amount of asset to attempt to free. */ function _emergencyWithdraw(uint256 _amount) internal virtual {} /*////////////////////////////////////////////////////////////// TokenizedStrategy HOOKS //////////////////////////////////////////////////////////////*/ /** * @notice Can deploy up to '_amount' of 'asset' in yield source. * @dev Callback for the TokenizedStrategy to call during a {deposit} * or {mint} to tell the strategy it can deploy funds. * * Since this can only be called after a {deposit} or {mint} * delegateCall to the TokenizedStrategy msg.sender == address(this). * * Unless a whitelist is implemented this will be entirely permissionless * and thus can be sandwiched or otherwise manipulated. * * @param _amount The amount of 'asset' that the strategy can * attempt to deposit in the yield source. */ function deployFunds(uint256 _amount) external virtual onlySelf { _deployFunds(_amount); } /** * @notice Should attempt to free the '_amount' of 'asset'. * @dev Callback for the TokenizedStrategy to call during a withdraw * or redeem to free the needed funds to service the withdraw. * * This can only be called after a 'withdraw' or 'redeem' delegateCall * to the TokenizedStrategy so msg.sender == address(this). * * @param _amount The amount of 'asset' that the strategy should attempt to free up. */ function freeFunds(uint256 _amount) external virtual onlySelf { _freeFunds(_amount); } /** * @notice Returns the accurate amount of all funds currently * held by the Strategy. * @dev Callback for the TokenizedStrategy to call during a report to * get an accurate accounting of assets the strategy controls. * * This can only be called after a report() delegateCall to the * TokenizedStrategy so msg.sender == address(this). * * @return . A trusted and accurate account for the total amount * of 'asset' the strategy currently holds including idle funds. */ function harvestAndReport() external virtual onlySelf returns (uint256) { return _harvestAndReport(); } /** * @notice Will call the internal '_tend' when a keeper tends the strategy. * @dev Callback for the TokenizedStrategy to initiate a _tend call in the strategy. * * This can only be called after a tend() delegateCall to the TokenizedStrategy * so msg.sender == address(this). * * We name the function `tendThis` so that `tend` calls are forwarded to * the TokenizedStrategy. * @param _totalIdle The amount of current idle funds that can be * deployed during the tend */ function tendThis(uint256 _totalIdle) external virtual onlySelf { _tend(_totalIdle); } /** * @notice Will call the internal '_emergencyWithdraw' function. * @dev Callback for the TokenizedStrategy during an emergency withdraw. * * This can only be called after a emergencyWithdraw() delegateCall to * the TokenizedStrategy so msg.sender == address(this). * * We name the function `shutdownWithdraw` so that `emergencyWithdraw` * calls are forwarded to the TokenizedStrategy. * * @param _amount The amount of asset to attempt to free. */ function shutdownWithdraw(uint256 _amount) external virtual onlySelf { _emergencyWithdraw(_amount); } /** * @dev Function used to delegate call the TokenizedStrategy with * certain `_calldata` and return any return values. * * This is used to setup the initial storage of the strategy, and * can be used by strategist to forward any other call to the * TokenizedStrategy implementation. * * @param _calldata The abi encoded calldata to use in delegatecall. * @return . The return value if the call was successful in bytes. */ function _delegateCall( bytes memory _calldata ) internal returns (bytes memory) { // Delegate call the tokenized strategy with provided calldata. (bool success, bytes memory result) = tokenizedStrategyAddress .delegatecall(_calldata); // If the call reverted. Return the error. if (!success) { assembly { let ptr := mload(0x40) let size := returndatasize() returndatacopy(ptr, 0, size) revert(ptr, size) } } // Return the result. return result; } /** * @dev Execute a function on the TokenizedStrategy and return any value. * * This fallback function will be executed when any of the standard functions * defined in the TokenizedStrategy are called since they wont be defined in * this contract. * * It will delegatecall the TokenizedStrategy implementation with the exact * calldata and return any relevant values. * */ fallback() external { // load our target address address _tokenizedStrategyAddress = tokenizedStrategyAddress; // Execute external function using delegatecall and return any value. assembly { // Copy function selector and any arguments. calldatacopy(0, 0, calldatasize()) // Execute function delegatecall. let result := delegatecall( gas(), _tokenizedStrategyAddress, 0, calldatasize(), 0, 0 ) // Get any return value returndatacopy(0, 0, returndatasize()) // Return any return value or error back to the caller switch result case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } } /** * @title Base Health Check * @author Yearn.finance * @notice This contract can be inherited by any Yearn * V3 strategy wishing to implement a health check during * the `report` function in order to prevent any unexpected * behavior from being permanently recorded as well as the * `checkHealth` modifier. * * A strategist simply needs to inherit this contract. Set * the limit ratios to the desired amounts and then * override `_harvestAndReport()` just as they otherwise * would. If the profit or loss that would be recorded is * outside the acceptable bounds the tx will revert. * * The healthcheck does not prevent a strategy from reporting * losses, but rather can make sure manual intervention is * needed before reporting an unexpected loss or profit. */ abstract contract BaseHealthCheck is BaseStrategy { // Can be used to determine if a healthcheck should be called. // Defaults to true; bool public doHealthCheck = true; uint256 internal constant MAX_BPS = 10_000; // Default profit limit to 100%. uint16 private _profitLimitRatio = uint16(MAX_BPS); // Defaults loss limit to 0. uint16 private _lossLimitRatio; constructor( address _asset, string memory _name ) BaseStrategy(_asset, _name) {} /** * @notice Returns the current profit limit ratio. * @dev Use a getter function to keep the variable private. * @return . The current profit limit ratio. */ function profitLimitRatio() public view returns (uint256) { return _profitLimitRatio; } /** * @notice Returns the current loss limit ratio. * @dev Use a getter function to keep the variable private. * @return . The current loss limit ratio. */ function lossLimitRatio() public view returns (uint256) { return _lossLimitRatio; } /** * @notice Set the `profitLimitRatio`. * @dev Denominated in basis points. I.E. 1_000 == 10%. * @param _newProfitLimitRatio The mew profit limit ratio. */ function setProfitLimitRatio( uint256 _newProfitLimitRatio ) external onlyManagement { _setProfitLimitRatio(_newProfitLimitRatio); } /** * @dev Internally set the profit limit ratio. Denominated * in basis points. I.E. 1_000 == 10%. * @param _newProfitLimitRatio The mew profit limit ratio. */ function _setProfitLimitRatio(uint256 _newProfitLimitRatio) internal { require(_newProfitLimitRatio > 0, "!zero profit"); require(_newProfitLimitRatio <= type(uint16).max, "!too high"); _profitLimitRatio = uint16(_newProfitLimitRatio); } /** * @notice Set the `lossLimitRatio`. * @dev Denominated in basis points. I.E. 1_000 == 10%. * @param _newLossLimitRatio The new loss limit ratio. */ function setLossLimitRatio( uint256 _newLossLimitRatio ) external onlyManagement { _setLossLimitRatio(_newLossLimitRatio); } /** * @dev Internally set the loss limit ratio. Denominated * in basis points. I.E. 1_000 == 10%. * @param _newLossLimitRatio The new loss limit ratio. */ function _setLossLimitRatio(uint256 _newLossLimitRatio) internal { require(_newLossLimitRatio < MAX_BPS, "!loss limit"); _lossLimitRatio = uint16(_newLossLimitRatio); } /** * @notice Turns the healthcheck on and off. * @dev If turned off the next report will auto turn it back on. * @param _doHealthCheck Bool if healthCheck should be done. */ function setDoHealthCheck(bool _doHealthCheck) public onlyManagement { doHealthCheck = _doHealthCheck; } /** * @notice OVerrides the default {harvestAndReport} to include a healthcheck. * @return _totalAssets New totalAssets post report. */ function harvestAndReport() external override onlySelf returns (uint256 _totalAssets) { // Let the strategy report. _totalAssets = _harvestAndReport(); // Run the healthcheck on the amount returned. _executeHealthCheck(_totalAssets); } /** * @dev To be called during a report to make sure the profit * or loss being recorded is within the acceptable bound. * * @param _newTotalAssets The amount that will be reported. */ function _executeHealthCheck(uint256 _newTotalAssets) internal virtual { if (!doHealthCheck) { doHealthCheck = true; return; } // Get the current total assets from the implementation. uint256 currentTotalAssets = TokenizedStrategy.totalAssets(); if (_newTotalAssets > currentTotalAssets) { require( ((_newTotalAssets - currentTotalAssets) <= (currentTotalAssets * uint256(_profitLimitRatio)) / MAX_BPS), "healthCheck" ); } else if (currentTotalAssets > _newTotalAssets) { require( (currentTotalAssets - _newTotalAssets <= ((currentTotalAssets * uint256(_lossLimitRatio)) / MAX_BPS)), "healthCheck" ); } } } // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 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://consensys.net/diligence/blog/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.8.0/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"); (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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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 /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 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)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @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). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // 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 cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } } interface IPendleMarket { function readTokens() external view returns (address _SY, address _PT, address _YT); function isExpired() external view returns (bool); } interface ISY { function deposit( address receiver, address tokenIn, uint256 amountTokenToDeposit, uint256 minSharesOut ) external payable returns (uint256 amountSharesOut); function redeem( address receiver, uint256 amountSharesToRedeem, address tokenOut, uint256 minTokenOut, bool burnFromInternalBalance ) external payable returns (uint256 amountTokenOut); function isValidTokenIn(address) external view returns (bool); function isValidTokenOut(address) external view returns (bool); function previewRedeem( address tokenOut, uint256 amountSharesToRedeem ) external view returns (uint256 amountTokenOut); } interface IPendleRouter { struct ApproxParams { uint256 guessMin; uint256 guessMax; uint256 guessOffchain; // pass 0 in to skip this variable uint256 maxIteration; // every iteration, the diff between guessMin and guessMax will be divided by 2 uint256 eps; // the max eps between the returned result & the correct result, base 1e18. Normally this number will be set // to 1e15 (1e18/1000 = 0.1%) } struct LimitOrderData { address limitRouter; uint256 epsSkipMarket; // only used for swap operations, will be ignored otherwise FillOrderParams[] normalFills; FillOrderParams[] flashFills; bytes optData; } struct FillOrderParams { Order order; bytes signature; uint256 makingAmount; } struct Order { uint256 salt; uint256 expiry; uint256 nonce; OrderType orderType; address token; address YT; address maker; address receiver; uint256 makingAmount; uint256 lnImpliedRate; uint256 failSafeRate; bytes permit; } enum OrderType { SY_FOR_PT, PT_FOR_SY, SY_FOR_YT, YT_FOR_SY } function swapExactSyForPt( address receiver, address market, uint256 exactSyIn, uint256 minPtOut, ApproxParams calldata guessPtOut, LimitOrderData calldata limit ) external returns (uint256 netPtOut, uint256 netSyFee); function swapExactPtForSy( address receiver, address market, uint256 exactPtIn, uint256 minSyOut, LimitOrderData calldata limit ) external returns (uint256 netSyOut, uint256 netSyFee); function redeemPyToSy( address receiver, address YT, uint256 netPyIn, uint256 minSyOut ) external returns (uint256 netSyOut); } interface IPendleOracle { function getPtToSyRate( address market, uint32 oracleDuration ) external view returns (uint256 rate); function getOracleState( address market, uint32 oracleDuration ) external view returns ( bool increaseCardinalityRequired, uint16 cardinalityRequired, bool oldestObservationSatisfied ); } /// @title yearn-v3-SingleSidedPTcore /// @author mil0x /// @notice yearn-v3 Strategy that invests into Pendle PT positions. contract SingleSidedPTcore is BaseHealthCheck { using SafeERC20 for ERC20; ///@notice Address of our Pendle market. address public market; address internal immutable oracle; ///@notice Oracle TWAP duration, in seconds. uint32 public oracleDuration; ///@notice Bool if the strategy is open for any depositors. Default = true. bool public open = true; ///@notice Mapping of addresses allowed to deposit. mapping(address => bool) public allowed; struct TradeParams { ///@notice Set the minimum asset amount to be converted to PT. Set to max to prevent PT buying. uint128 minAssetAmountToPT; ///@notice The max in asset will be invested by the keeper at a time. uint128 maxSingleTrade; } ///@notice Parameters used to contrin size of strategy investing into PT. TradeParams public tradeParams; ///@notice The total deposit limit for the strategy. Use in case we want to cap a given strategy. uint256 public depositLimit = type(uint256).max; address internal constant pendleRouter = 0x888888888889758F76e7103c6CbF23ABbF58F946; ///@notice Parameters passed to Pendle's router for swaps in using binary search. IPendleRouter.ApproxParams public routerParams; ///@notice Address of this market's SY token. address public immutable SY; ///@notice Address of this market's PT token. address public PT; address internal YT; ///@notice Amount in Basis Points to allow for slippage when reporting. uint256 public swapSlippageBPS; ///@notice Amount in Basis Points to account for as buffer when reporting. Can also manually account for bigger depeg scenarios. uint256 public bufferSlippageBPS; // Struct for all variables involved in tendTrigger struct TendTriggerParams { ///@notice The amount in asset that will trigger a tend if idle. uint128 depositTrigger; ///@notice The max amount the base fee can be for a tend to happen. uint48 maxTendBaseFee; ///@notice Minimum time between deposits to wait. uint40 minDepositInterval; ///@notice Time stamp of the last deployment of funds. uint40 lastDeposit; } ///@notice Contains adjustable variables that govern when to tend this strategy. TendTriggerParams public tendTriggerParams; ///@notice Yearn governance address public immutable GOV; uint256 internal constant WAD = 1e18; constructor( address _asset, address _market, address _oracle, address _GOV, string memory _name ) BaseHealthCheck(_asset, _name) { market = _market; require(!_isExpired(), "expired"); oracle = _oracle; //Default oracle duration to 1 hour price smoothing recommendation by Pendle Finance oracleDuration = 3600; //Default maxSingleTrade to 15 ETH as a majority of markets are ETH based. Change this for non-ETH. tradeParams.maxSingleTrade = 15e18; (SY, PT, YT) = IPendleMarket(_market).readTokens(); require(ISY(SY).isValidTokenOut(_asset), "!valid out"); require(ISY(SY).isValidTokenIn(_asset), "!valid in"); // Default slippage to 0.5%. swapSlippageBPS = 50; bufferSlippageBPS = 50; routerParams.guessMax = type(uint256).max; routerParams.maxIteration = 256; routerParams.eps = 1e15; // max 0.1% unused TendTriggerParams memory _tendTriggerParams; _tendTriggerParams.depositTrigger = 5e18; // The amount in asset that will trigger a tend if idle. Default to 5 ETH; update for non-ETH. _tendTriggerParams.maxTendBaseFee = 20e9; // The max amount the base fee can be for a tend to happen. Default max tend fee to 20 gwei. _tendTriggerParams.minDepositInterval = 43200; // Minimum time between deposits to wait. Default min deposit interval to 12 hours. tendTriggerParams = _tendTriggerParams; // Allow a 500% gain. _setProfitLimitRatio(500_00); GOV = _GOV; //approvals: ERC20(_asset).forceApprove(SY, type(uint256).max); ERC20(SY).forceApprove(pendleRouter, type(uint256).max); ERC20(PT).forceApprove(pendleRouter, type(uint256).max); } /*////////////////////////////////////////////////////////////// INTERNAL //////////////////////////////////////////////////////////////*/ function _deployFunds(uint256 _amount) internal override { //do nothing, we want to only have the keeper swap funds } function _invest(uint256 _amount) internal { //asset --> SY ISY(SY).deposit(address(this), address(asset), _amount, 0); _amount = ERC20(SY).balanceOf(address(this)); //SY --> PT IPendleRouter.LimitOrderData memory limit; //skip limit order by passing zero address uint256 minPTout = (_SYtoPT(_amount) * (MAX_BPS - swapSlippageBPS)) / MAX_BPS; //calculate minimum expected PT out IPendleRouter(pendleRouter).swapExactSyForPt( address(this), market, _amount, minPTout, routerParams, limit ); // Update the last time that we deposited. tendTriggerParams.lastDeposit = uint40(block.timestamp); } function _freeFunds(uint256 _amount) internal override { //Redeem PT shares proportional to the SSPT shares redeemed: uint256 totalAssets = TokenizedStrategy.totalAssets(); uint256 totalDebt = totalAssets - _balanceOfAsset(); uint256 PTtoUninvest = (_balanceOfPT() * _amount) / totalDebt; _uninvest(PTtoUninvest); } function _uninvest(uint256 currentBalance) internal returns (uint256) { if (currentBalance == 0) return 0; //PT --> SY if (_isExpired()) { //if expired, redeem PY to SY currentBalance = IPendleRouter(pendleRouter).redeemPyToSy( address(this), YT, currentBalance, 0 ); } else { IPendleRouter.LimitOrderData memory limit; //skip limit order by passing zero address // We don't enforce any min amount out since withdrawer's can use 'maxLoss' (currentBalance, ) = IPendleRouter(pendleRouter).swapExactPtForSy( address(this), market, currentBalance, 0, limit ); if (currentBalance == 0) return 0; } //SY --> asset // We don't enforce any min amount out since withdrawers can use 'maxLoss' return ISY(SY).redeem( address(this), currentBalance, address(asset), 0, false ); } function _harvestAndReport() internal override returns (uint256 _totalAssets) { if (!_isExpired() && !TokenizedStrategy.isShutdown()) { uint256 assetBalance = _balanceOfAsset(); TradeParams memory _tradeParams = tradeParams; if (assetBalance > _tradeParams.minAssetAmountToPT) { _invest(_min(assetBalance, _tradeParams.maxSingleTrade)); } } _totalAssets = _balanceOfAsset() + (_PTtoAsset(_balanceOfPT()) * (MAX_BPS - bufferSlippageBPS)) / MAX_BPS; //reduce PT balance by bufferSlippageBPS to account for the fact that it will need to be swapped back to asset } function _SYtoPT(uint256 _amount) internal view returns (uint256) { return (_amount * WAD) / IPendleOracle(oracle).getPtToSyRate(market, oracleDuration); } function _PTtoSY(uint256 _amount) internal view returns (uint256) { return (_amount * IPendleOracle(oracle).getPtToSyRate(market, oracleDuration)) / WAD; } function _PTtoAsset(uint256 _amount) internal view returns (uint256) { return ISY(SY).previewRedeem(address(asset), _PTtoSY(_amount)); } function _tend(uint256) internal override { _invest(_min(_balanceOfAsset(), tradeParams.maxSingleTrade)); } function _tendTrigger() internal view override returns (bool _shouldTend) { TendTriggerParams memory _tendTriggerParams = tendTriggerParams; if ( !_isExpired() && block.timestamp - _tendTriggerParams.lastDeposit > _tendTriggerParams.minDepositInterval && _balanceOfAsset() > _tendTriggerParams.depositTrigger && tradeParams.maxSingleTrade > 0 && !TokenizedStrategy.isShutdown() ) { _shouldTend = block.basefee < _tendTriggerParams.maxTendBaseFee; } } function availableDepositLimit( address _owner ) public view override returns (uint256) { // If the owner is whitelisted or the strategy is open. if (allowed[_owner] || open) { uint256 totalDeposits = TokenizedStrategy.totalAssets(); if (depositLimit > totalDeposits) { return depositLimit - totalDeposits; } else { return 0; } } else { return 0; } } function _balanceOfAsset() internal view returns (uint256) { return asset.balanceOf(address(this)); } function _balanceOfPT() internal view returns (uint256) { return ERC20(PT).balanceOf(address(this)); } function _isExpired() internal view returns (bool) { return IPendleMarket(market).isExpired(); } function _checkOracle( address _market, uint32 _oracleDuration ) internal view { ( bool increaseCardinalityRequired, , bool oldestObservationSatisfied ) = IPendleOracle(oracle).getOracleState(_market, _oracleDuration); if (increaseCardinalityRequired || !oldestObservationSatisfied) { revert("oracle not ready"); } } function _min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /*////////////////////////////////////////////////////////////// EXTERNAL: //////////////////////////////////////////////////////////////*/ function balanceOfAsset() external view returns (uint256) { return _balanceOfAsset(); } function balanceOfPT() external view returns (uint256) { return _balanceOfPT(); } function isExpired() external view returns (bool) { return _isExpired(); } /** * @notice Set oracle duration price smoothing * @param _oracleDuration twap duration in seconds */ function setOracleDuration( uint32 _oracleDuration ) external onlyEmergencyAuthorized { require(_oracleDuration >= 900, "duration too low"); _checkOracle(market, _oracleDuration); oracleDuration = _oracleDuration; } /** * @notice Set the tradeParams for the strategy to decide on minimum investment and maximum single investments for the keeper. * @param _minAssetAmountToPT Set the minimum amount in asset that should be converted to PT. Set this to max in order to not trigger any PT buying. * @param _maxSingleTrade Set the max in asset amount that will be invested by the keeper at a time. Can also be used to pause keeper investments. */ function setTradeParams( uint128 _minAssetAmountToPT, uint128 _maxSingleTrade ) external onlyManagement { require( _maxSingleTrade <= type(uint128).max && _minAssetAmountToPT <= type(uint128).max, "too large" ); require(_maxSingleTrade >= _minAssetAmountToPT, "wrong order"); require(tendTriggerParams.depositTrigger >= _minAssetAmountToPT, "minAsset too large"); TradeParams memory _tradeParams; _tradeParams.minAssetAmountToPT = _minAssetAmountToPT; _tradeParams.maxSingleTrade = _maxSingleTrade; tradeParams = _tradeParams; } /** * @notice Set the routerParams for the pendleRouter. Pendle's AMM only supports the built-in swapSyForExactPt. To execute a swapExactSyForPt, the * router will conduct a binary search to determine the amount of PT to swap. * @param _guessMin The minimum value for binary search. Default: 0. * @param _guessMax The maximum value for binary search. Default: type(uint256).max. * @param _maxIteration The maximum number of times binary search will be performed. Default: 256. * @param _eps The precision of binary search - the maximum proportion of the input that can be unused. Default: 1e15 == max 0.1% unused. * Alternatively: 1e14 implies that no more than 0.01% unused. */ function setRouterParams( uint256 _guessMin, uint256 _guessMax, uint256 _maxIteration, uint256 _eps ) external onlyManagement { routerParams.guessMin = _guessMin; // default: 0 routerParams.guessMax = _guessMax; // default: type(uint256).max routerParams.maxIteration = _maxIteration; // default: 256 routerParams.eps = _eps; // default: 1e15 == max 0.1% unused. Alternatively: 1e14 implies that no more than 0.01% unused. } /** * @notice Set the tendTriggerParams for all variables involved in tendTrigger. * @param _depositTrigger The amount in asset that will trigger a tend if idle. * @param _maxTendBaseFee The max amount the base fee can be for a tend to happen in wei. * @param _minDepositInterval Minimum time between deposits to wait in seconds. */ function setTendTriggerParams( uint128 _depositTrigger, uint48 _maxTendBaseFee, uint40 _minDepositInterval ) external onlyManagement { require(_minDepositInterval > 0, "interval too low"); require(_depositTrigger <= type(uint128).max, "too large"); require(_depositTrigger >= tradeParams.minAssetAmountToPT, "trigger too small"); tendTriggerParams.depositTrigger = _depositTrigger; tendTriggerParams.maxTendBaseFee = _maxTendBaseFee; tendTriggerParams.minDepositInterval = _minDepositInterval; } /** * @notice Set the deposit limit in asset amount. Set this to 0 to disallow deposits. * @param _depositLimit the deposit limit in asset units */ function setDepositLimit(uint256 _depositLimit) external onlyManagement { depositLimit = _depositLimit; } /** * @notice Set the slippage for keeper investments in basis points. * @param _swapSlippageBPS the maximum slippage in basis points (BPS) */ function setSwapSlippageBPS( uint256 _swapSlippageBPS ) external onlyManagement { require(_swapSlippageBPS <= MAX_BPS); swapSlippageBPS = _swapSlippageBPS; } /** * @notice Set the buffer for reports in basis points. Can also be used to manually account for bigger depeg scenarios * @param _bufferSlippageBPS the buffer slippage in basis points (BPS) */ function setBufferSlippageBPS( uint256 _bufferSlippageBPS ) external onlyManagement { require(_bufferSlippageBPS <= MAX_BPS); bufferSlippageBPS = _bufferSlippageBPS; } /** * @notice Change if anyone can deposit in or only white listed addresses * @param _open the bool deciding if anyone can deposit (true) or only whitelisted addresses (false) */ function setOpen(bool _open) external onlyManagement { open = _open; } /** * @notice Set or update an addresses whitelist status. * @param _address the address for which to change the whitelist status * @param _allowed the bool to set as whitelisted (true) or not (false) */ function setAllowed( address _address, bool _allowed ) external onlyManagement { allowed[_address] = _allowed; } /*////////////////////////////////////////////////////////////// EMERGENCY & GOVERNANCE: //////////////////////////////////////////////////////////////*/ /** * @notice Manually pull funds out from the PT stack without shuting down. This will also stop keeper investments. * @param _amount the PT amount to uninvest into asset * @param _expectedAssetAmountOut the minimum acceptable asset amount as a result of uninvestment */ function manualWithdraw( uint256 _amount, uint256 _expectedAssetAmountOut ) external onlyEmergencyAuthorized { tradeParams.maxSingleTrade = 0; uint256 currentBalance = _balanceOfPT(); if (_amount > currentBalance) { _amount = currentBalance; } uint256 _amountOut = _uninvest(_amount); require(_amountOut >= _expectedAssetAmountOut, "too little amountOut"); } /** * @notice Manually pull funds out from the PT stack after the strategy has been shutdown. * @param _amount the PT amount to uninvest into asset */ function _emergencyWithdraw(uint256 _amount) internal override { uint256 currentBalance = _balanceOfPT(); if (_amount > currentBalance) { _amount = currentBalance; } uint256 expectedAssetAmountOut = _PTtoAsset(_amount); uint256 _amountOut = _uninvest(_amount); require( _amountOut >= (expectedAssetAmountOut * (MAX_BPS - swapSlippageBPS)) / MAX_BPS, "too little amountOut" ); } /** * @notice Redeem all PT into asset and rollover the market into a new maturity. Only callable by governance. * @param _market the market address (not PT address) for the new maturity to rollover into * @param _minAssetAmountOut the acceptable minimum amount of asset out for the PT amount currently held by the strategy */ function rolloverMaturity( address _market, uint256 _minAssetAmountOut ) external onlyGovernance { require(_isExpired(), "not expired"); require(_market != address(0), "!market"); require(market != _market, "same market"); //check new market exists long enough for preset oracleDuration _checkOracle(_market, oracleDuration); //redeem all PT to SY uint256 currentBalance = _balanceOfPT(); if (currentBalance > 0) { currentBalance = IPendleRouter(pendleRouter).redeemPyToSy( address(this), YT, currentBalance, 0 ); } //set addresses to new maturity market = _market; require(!_isExpired(), "expired"); (address _SY, address _PT, address _YT) = IPendleMarket(_market) .readTokens(); require(_SY == SY, "wrong SY"); PT = _PT; YT = _YT; ERC20(_PT).forceApprove(pendleRouter, type(uint256).max); //redeem all SY into asset (let keeper move asset to new PT over time) if (currentBalance == 0 && _minAssetAmountOut == 0) return; ISY(SY).redeem( address(this), currentBalance, address(asset), _minAssetAmountOut, false ); } /** * @notice Sweep of non-asset ERC20 tokens to governance (onlyGovernance) * @param _token The ERC20 token to sweep */ function sweep(address _token) external onlyGovernance { require(_token != address(asset), "!asset"); require(_token != PT, "!PT"); ERC20(_token).safeTransfer(GOV, ERC20(_token).balanceOf(address(this))); } modifier onlyGovernance() { require(msg.sender == GOV, "!gov"); _; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"address","name":"_market","type":"address"},{"internalType":"address","name":"_oracle","type":"address"},{"internalType":"address","name":"_GOV","type":"address"},{"internalType":"string","name":"_name","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"GOV","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"allowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"availableDepositLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"availableWithdrawLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceOfAsset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceOfPT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bufferSlippageBPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deployFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"doHealthCheck","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"freeFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"harvestAndReport","outputs":[{"internalType":"uint256","name":"_totalAssets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isExpired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lossLimitRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_expectedAssetAmountOut","type":"uint256"}],"name":"manualWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"market","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"open","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracleDuration","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"profitLimitRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_market","type":"address"},{"internalType":"uint256","name":"_minAssetAmountOut","type":"uint256"}],"name":"rolloverMaturity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"routerParams","outputs":[{"internalType":"uint256","name":"guessMin","type":"uint256"},{"internalType":"uint256","name":"guessMax","type":"uint256"},{"internalType":"uint256","name":"guessOffchain","type":"uint256"},{"internalType":"uint256","name":"maxIteration","type":"uint256"},{"internalType":"uint256","name":"eps","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bool","name":"_allowed","type":"bool"}],"name":"setAllowed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_bufferSlippageBPS","type":"uint256"}],"name":"setBufferSlippageBPS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_depositLimit","type":"uint256"}],"name":"setDepositLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_doHealthCheck","type":"bool"}],"name":"setDoHealthCheck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newLossLimitRatio","type":"uint256"}],"name":"setLossLimitRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_open","type":"bool"}],"name":"setOpen","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_oracleDuration","type":"uint32"}],"name":"setOracleDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newProfitLimitRatio","type":"uint256"}],"name":"setProfitLimitRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_guessMin","type":"uint256"},{"internalType":"uint256","name":"_guessMax","type":"uint256"},{"internalType":"uint256","name":"_maxIteration","type":"uint256"},{"internalType":"uint256","name":"_eps","type":"uint256"}],"name":"setRouterParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_swapSlippageBPS","type":"uint256"}],"name":"setSwapSlippageBPS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"_depositTrigger","type":"uint128"},{"internalType":"uint48","name":"_maxTendBaseFee","type":"uint48"},{"internalType":"uint40","name":"_minDepositInterval","type":"uint40"}],"name":"setTendTriggerParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"_minAssetAmountToPT","type":"uint128"},{"internalType":"uint128","name":"_maxSingleTrade","type":"uint128"}],"name":"setTradeParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"shutdownWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapSlippageBPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_totalIdle","type":"uint256"}],"name":"tendThis","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tendTrigger","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tendTriggerParams","outputs":[{"internalType":"uint128","name":"depositTrigger","type":"uint128"},{"internalType":"uint48","name":"maxTendBaseFee","type":"uint48"},{"internalType":"uint40","name":"minDepositInterval","type":"uint40"},{"internalType":"uint40","name":"lastDeposit","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenizedStrategyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tradeParams","outputs":[{"internalType":"uint128","name":"minAssetAmountToPT","type":"uint128"},{"internalType":"uint128","name":"maxSingleTrade","type":"uint128"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6101206040526000805462ffffff60ff60e81b01191662271001600160e81b011790556000196003553480156200003557600080fd5b50604051620041e5380380620041e5833981016040819052620000589162000af4565b6001600160a01b0385166080523060a0526040518590829082908290620000c59062000091908490849033908190819060240162000c28565b60408051601f198184030181529190526020810180516001600160e01b03908116634b839d7360e11b17909152620004c116565b505073bb51273d6c746910c7c06fe718f30c936170fed07f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55505060008054600160281b600160c81b031916650100000000006001600160a01b03881602179055506200013162000555565b156200016e5760405162461bcd60e51b8152602060048201526007602482015266195e1c1a5c995960ca1b60448201526064015b60405180910390fd5b6001600160a01b0383811660c0526000805463ffffffff60c81b191660e160cc1b179055600280546001600160801b031665340aad21b3b760921b17905560408051630b2339af60e21b8152905191861691632c8ce6bc916004808201926060929091908290030181865afa158015620001ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000212919062000c6b565b600a80546001600160a01b03199081166001600160a01b0393841617909155600980549091169282169290921790915590811660e0819052604051633c21b3eb60e11b815291871660048301529063784367d690602401602060405180830381865afa15801562000287573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002ad919062000cb5565b620002e85760405162461bcd60e51b815260206004820152600a602482015269085d985b1a59081bdd5d60b21b604482015260640162000165565b60e051604051637d2d278360e11b81526001600160a01b0387811660048301529091169063fa5a4f0690602401602060405180830381865afa15801562000333573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000359919062000cb5565b620003935760405162461bcd60e51b815260206004820152600960248201526810bb30b634b21034b760b91b604482015260640162000165565b6032600b819055600c5560001960055561010060075566038d7ea4c680006008556040805160808101825260006060820152674563918244f4000081526404a817c800602082015261a8c09181019190915277a8c00004a817c80000000000000000004563918244f40000600d556200040e61c350620005d5565b6001600160a01b038381166101005260e0516200043d9188169060001962000674602090811b620018ee17901c565b6200047a73888888888889758f76e7103c6cbf23abbf58f94660001960e0516001600160a01b03166200067460201b620018ee179092919060201c565b600954620004b5906001600160a01b031673888888888889758f76e7103c6cbf23abbf58f94660001962000674602090811b620018ee17901c565b50505050505062000d0c565b606060008073bb51273d6c746910c7c06fe718f30c936170fed06001600160a01b031684604051620004f4919062000cd9565b600060405180830381855af49150503d806000811462000531576040519150601f19603f3d011682016040523d82523d6000602084013e62000536565b606091505b5091509150816200054e576040513d806000833e8082fd5b9392505050565b60008060059054906101000a90046001600160a01b03166001600160a01b0316632f13b60c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620005aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005d0919062000cb5565b905090565b60008111620006165760405162461bcd60e51b815260206004820152600c60248201526b085e995c9bc81c1c9bd99a5d60a21b604482015260640162000165565b61ffff811115620006565760405162461bcd60e51b8152602060048201526009602482015268042e8dede40d0d2ced60bb1b604482015260640162000165565b6000805461ffff9092166101000262ffff0019909216919091179055565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152620006ce90859083906200074a16565b62000744576040516001600160a01b0384166024820152600060448201526200073890859063095ea7b360e01b9060640160408051808303601f190181529190526020810180516001600160e01b0319939093166001600160e01b03938416179052906200080216565b62000744848262000802565b50505050565b6000806000846001600160a01b03168460405162000769919062000cd9565b6000604051808303816000865af19150503d8060008114620007a8576040519150601f19603f3d011682016040523d82523d6000602084013e620007ad565b606091505b5091509150818015620007db575080511580620007db575080806020019051810190620007db919062000cb5565b8015620007f95750620007f985620008e860201b620019b01760201c565b95945050505050565b60006200085e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620008f760201b620019bf179092919060201c565b90508051600014806200088257508080602001905181019062000882919062000cb5565b620008e35760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000165565b505050565b6001600160a01b03163b151590565b606062000908848460008562000910565b949350505050565b606082471015620009735760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000165565b600080866001600160a01b0316858760405162000991919062000cd9565b60006040518083038185875af1925050503d8060008114620009d0576040519150601f19603f3d011682016040523d82523d6000602084013e620009d5565b606091505b509092509050620009e987838387620009f4565b979650505050505050565b6060831562000a6857825160000362000a60576001600160a01b0385163b62000a605760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000165565b508162000908565b62000908838381511562000a7f5781518083602001fd5b8060405162461bcd60e51b815260040162000165919062000cf7565b80516001600160a01b038116811462000ab357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101562000aeb57818101518382015260200162000ad1565b50506000910152565b600080600080600060a0868803121562000b0d57600080fd5b62000b188662000a9b565b945062000b286020870162000a9b565b935062000b386040870162000a9b565b925062000b486060870162000a9b565b60808701519092506001600160401b038082111562000b6657600080fd5b818801915088601f83011262000b7b57600080fd5b81518181111562000b905762000b9062000ab8565b604051601f8201601f19908116603f0116810190838211818310171562000bbb5762000bbb62000ab8565b816040528281528b602084870101111562000bd557600080fd5b62000be883602083016020880162000ace565b80955050505050509295509295909350565b6000815180845262000c1481602086016020860162000ace565b601f01601f19169290920160200192915050565b600060018060a01b03808816835260a0602084015262000c4c60a084018862000bfa565b9581166040840152938416606083015250911660809091015292915050565b60008060006060848603121562000c8157600080fd5b62000c8c8462000a9b565b925062000c9c6020850162000a9b565b915062000cac6040850162000a9b565b90509250925092565b60006020828403121562000cc857600080fd5b815180151581146200054e57600080fd5b6000825162000ced81846020870162000ace565b9190910192915050565b6020815260006200054e602083018462000bfa565b60805160a05160c05160e051610100516133ad62000e386000396000818161032b015281816106f1015281816108170152610f330152600081816105a5015281816111ef0152818161131b015281816122bf0152818161279f0152818161285401526129c401526000818161236101528181612b1a0152612bea0152600081816108ce01528181610a9001528181610b1b01528181610be101528181610d1301528181610db301528181610e44015281816113a701528181611432015281816114bd0152818161153c01528181611641015281816116cc0152818161174c01528181611b2e01528181611c0c01528181611d5a0152611f52015260008181610752015281816112e50152818161200701528181612289015281816127ce01526129f301526133ad6000f3fe608060405234801561001057600080fd5b50600436106102695760003560e01c80637d96993211610151578063c05bd92d116100c3578063d696860111610087578063d69686011461067d578063d94073d414610690578063ecf70858146106a3578063f462bbff146106ac578063fcfff16f146106bf578063fde813a8146106d357610269565b8063c05bd92d146105ed578063cefba47414610600578063cf683c701461062c578063d19a3bb81461063f578063d63a8e111461065a57610269565b8063a4a7799511610115578063a4a77995146104ff578063ab1c99941461057a578063ac00ff261461058d578063afd27bf5146105a0578063bc06b529146105c7578063bdc8144b146105da57610269565b80637d9699321461049957806380f55605146104ac578063950b3d73146104c65780639d7fb70c146104d9578063a0ef795b146104ec57610269565b80633d6cb575116101ea5780634a5d0943116101ae5780634a5d094314610437578063503160d9146104485780635d265d3f1461045b5780636718835f146104715780636fdca5e01461047e578063797bf3431461049157610269565b80633d6cb575146103e357806345b1993f146103f65780634697f05d1461040957806346aa2f121461041c57806349317f1d1461042f57610269565b80631eab62a9116102315780631eab62a914610365578063256d8a231461036e5780632b24a878146103b05780632f13b60c146103b85780633ba24f81146103d057610269565b806301681a62146102a457806304bd4629146102b757806309b2c8a8146102df5780631809bca51461031d578063180cb47f14610326575b73bb51273d6c746910c7c06fe718f30c936170fed03660008037600080366000845af43d6000803e80801561029d573d6000f35b3d6000fd5b005b6102a26102b2366004612cd6565b6106e6565b6102cc6102c5366004612cd6565b5060001990565b6040519081526020015b60405180910390f35b6002546102fd906001600160801b0380821691600160801b90041682565b604080516001600160801b039384168152929091166020830152016102d6565b6102cc600c5481565b61034d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102d6565b6102cc600b5481565b600454600554600654600754600854610388949392919085565b604080519586526020860194909452928401919091526060830152608082015260a0016102d6565b6102cc6108a0565b6103c06108af565b60405190151581526020016102d6565b6102a26103de366004612d0a565b6108b9565b6102a26103f1366004612d68565b610a6a565b6102a2610404366004612d81565b610a7b565b6102a2610417366004612dc1565b610b06565b6102cc61042a366004612cd6565b610ba8565b6102cc610c98565b600054610100900461ffff166102cc565b6102a2610456366004612d68565b610cb8565b610463610cc0565b6040516102d6929190612e4a565b6000546103c09060ff1681565b6102a261048c366004612e65565b610cfe565b6102cc610d94565b6000546301000000900461ffff166102cc565b60005461034d90600160281b90046001600160a01b031681565b6102a26104d4366004612d68565b610d9e565b6102a26104e7366004612d68565b610e1e565b6102a26104fa366004612e82565b610e2f565b600d5461053c906001600160801b0381169065ffffffffffff600160801b8204169064ffffffffff600160b01b8204811691600160d81b90041684565b604080516001600160801b03909516855265ffffffffffff909316602085015264ffffffffff918216928401929092521660608201526080016102d6565b6102a2610588366004612ea4565b610f28565b6102a261059b366004612e65565b611392565b61034d7f000000000000000000000000000000000000000000000000000000000000000081565b6102a26105d5366004612d68565b61141d565b6102a26105e8366004612d68565b6114a8565b6102a26105fb366004612ed0565b611527565b60005461061790600160c81b900463ffffffff1681565b60405163ffffffff90911681526020016102d6565b6102a261063a366004612d68565b61162c565b61034d73bb51273d6c746910c7c06fe718f30c936170fed081565b6103c0610668366004612cd6565b60016020526000908152604090205460ff1681565b6102a261068b366004612d68565b6116b7565b60095461034d906001600160a01b031681565b6102cc60035481565b6102a26106ba366004612ef6565b611737565b6000546103c090600160e81b900460ff1681565b6102a26106e1366004612d68565b6118dd565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146107505760405162461bcd60e51b81526004016107479060208082526004908201526310b3b7bb60e11b604082015260600190565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316036107ba5760405162461bcd60e51b815260206004820152600660248201526508585cdcd95d60d21b6044820152606401610747565b6009546001600160a01b03908116908216036107fe5760405162461bcd60e51b815260206004820152600360248201526208541560ea1b6044820152606401610747565b6040516370a0823160e01b815230600482015261089d907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610868573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061088c9190612f29565b6001600160a01b03841691906119d6565b50565b60006108aa611a0b565b905090565b60006108aa611a79565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a6499060240160006040518083038186803b15801561091857600080fd5b505afa15801561092c573d6000803e3d6000fd5b5050505060008164ffffffffff161161097a5760405162461bcd60e51b815260206004820152601060248201526f696e74657276616c20746f6f206c6f7760801b6044820152606401610747565b6001600160801b0383811611156109bf5760405162461bcd60e51b8152602060048201526009602482015268746f6f206c6172676560b81b6044820152606401610747565b6002546001600160801b039081169084161015610a125760405162461bcd60e51b81526020600482015260116024820152701d1c9a59d9d95c881d1bdbc81cdb585b1b607a1b6044820152606401610747565b600d805464ffffffffff909216600160b01b0264ffffffffff60b01b1965ffffffffffff909416600160801b026001600160b01b03199093166001600160801b03909516949094179190911791909116919091179055565b610a72611af1565b61089d81611b2a565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a6499060240160006040518083038186803b158015610ada57600080fd5b505afa158015610aee573d6000803e3d6000fd5b50505060049490945560059290925560075560085550565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a6499060240160006040518083038186803b158015610b6557600080fd5b505afa158015610b79573d6000803e3d6000fd5b505050506001600160a01b03919091166000908152600160205260409020805460ff1916911515919091179055565b6001600160a01b03811660009081526001602052604081205460ff1680610bd85750600054600160e81b900460ff165b15610c8b5760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301e1d1146040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c619190612f29565b9050806003541115610c825780600354610c7b9190612f58565b9392505050565b50600092915050565b506000919050565b919050565b6000610ca2611af1565b610caa611bf8565b9050610cb581611d3c565b90565b61089d611af1565b60006060610ccc611e86565b6040805160048152602481019091526020810180516001600160e01b031663440368a360e01b17905290939092509050565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a6499060240160006040518083038186803b158015610d5d57600080fd5b505afa158015610d71573d6000803e3d6000fd5b505060008054931515600160e81b0260ff60e81b19909416939093179092555050565b60006108aa611fef565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a6499060240160006040518083038186803b158015610dfd57600080fd5b505afa158015610e11573d6000803e3d6000fd5b5050505061089d8161203e565b610e26611af1565b61089d816120d9565b6040516320b8029160e21b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906382e00a449060240160006040518083038186803b158015610e8e57600080fd5b505afa158015610ea2573d6000803e3d6000fd5b5050600280546001600160801b031690555060009050610ec0611a0b565b905080831115610ece578092505b6000610ed9846120ff565b905082811015610f225760405162461bcd60e51b81526020600482015260146024820152731d1bdbc81b1a5d1d1b1948185b5bdd5b9d13dd5d60621b6044820152606401610747565b50505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610f895760405162461bcd60e51b81526004016107479060208082526004908201526310b3b7bb60e11b604082015260600190565b610f91611a79565b610fcb5760405162461bcd60e51b815260206004820152600b60248201526a1b9bdd08195e1c1a5c995960aa1b6044820152606401610747565b6001600160a01b03821661100b5760405162461bcd60e51b8152602060048201526007602482015266085b585c9ad95d60ca1b6044820152606401610747565b6000546001600160a01b03808416600160281b909204160361105d5760405162461bcd60e51b815260206004820152600b60248201526a1cd85b59481b585c9ad95d60aa1b6044820152606401610747565b600054611078908390600160c81b900463ffffffff16612332565b6000611082611a0b565b9050801561111b57600a5460405163339748cb60e01b815273888888888889758f76e7103c6cbf23abbf58f9469163339748cb916110d59130916001600160a01b03909116908690600090600401612f6b565b6020604051808303816000875af11580156110f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111189190612f29565b90505b6000805465010000000000600160c81b031916600160281b6001600160a01b03861602179055611149611a79565b156111805760405162461bcd60e51b8152602060048201526007602482015266195e1c1a5c995960ca1b6044820152606401610747565b6000806000856001600160a01b0316632c8ce6bc6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156111c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e79190612f94565b9250925092507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316146112595760405162461bcd60e51b815260206004820152600860248201526777726f6e6720535960c01b6044820152606401610747565b600980546001600160a01b038085166001600160a01b03199283168117909355600a8054918516919092161790556112a89073888888888889758f76e7103c6cbf23abbf58f9466000196118ee565b831580156112b4575084155b156112c157505050505050565b60405163769f8e5d60e01b8152306004820152602481018590526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116604483015260648201879052600060848301527f0000000000000000000000000000000000000000000000000000000000000000169063769f8e5d9060a4016020604051808303816000875af1158015611364573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113889190612f29565b50505050505b5050565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a6499060240160006040518083038186803b1580156113f157600080fd5b505afa158015611405573d6000803e3d6000fd5b50506000805460ff1916931515939093179092555050565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a6499060240160006040518083038186803b15801561147c57600080fd5b505afa158015611490573d6000803e3d6000fd5b505050506127108111156114a357600080fd5b600c55565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a6499060240160006040518083038186803b15801561150757600080fd5b505afa15801561151b573d6000803e3d6000fd5b50505060039190915550565b6040516320b8029160e21b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906382e00a449060240160006040518083038186803b15801561158657600080fd5b505afa15801561159a573d6000803e3d6000fd5b505050506103848163ffffffff1610156115e95760405162461bcd60e51b815260206004820152601060248201526f6475726174696f6e20746f6f206c6f7760801b6044820152606401610747565b60005461160690600160281b90046001600160a01b031682612332565b6000805463ffffffff909216600160c81b0263ffffffff60c81b19909216919091179055565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a6499060240160006040518083038186803b15801561168b57600080fd5b505afa15801561169f573d6000803e3d6000fd5b505050506127108111156116b257600080fd5b600b55565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a6499060240160006040518083038186803b15801561171657600080fd5b505afa15801561172a573d6000803e3d6000fd5b5050505061089d8161241b565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a6499060240160006040518083038186803b15801561179657600080fd5b505afa1580156117aa573d6000803e3d6000fd5b5050506001600160801b0382811611801591506117d057506001600160801b0382811611155b6118085760405162461bcd60e51b8152602060048201526009602482015268746f6f206c6172676560b81b6044820152606401610747565b816001600160801b0316816001600160801b031610156118585760405162461bcd60e51b815260206004820152600b60248201526a3bb937b7339037b93232b960a91b6044820152606401610747565b600d546001600160801b03808416911610156118ab5760405162461bcd60e51b81526020600482015260126024820152716d696e417373657420746f6f206c6172676560701b6044820152606401610747565b604080518082019091526001600160801b03928316808252919092166020909201829052600160801b90910217600255565b6118e5611af1565b61089d8161247c565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261193f848261251b565b610f22576040516001600160a01b0384166024820152600060448201526119a690859063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526125c2565b610f2284826125c2565b6001600160a01b03163b151590565b60606119ce8484600085612697565b949350505050565b6040516001600160a01b038316602482015260448101829052611a0690849063a9059cbb60e01b9060640161196f565b505050565b6009546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a08231906024015b602060405180830381865afa158015611a55573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108aa9190612f29565b60008060059054906101000a90046001600160a01b03166001600160a01b0316632f13b60c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611acd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108aa9190612fd6565b333014611b285760405162461bcd60e51b815260206004820152600560248201526410b9b2b63360d91b6044820152606401610747565b565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301e1d1146040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bae9190612f29565b90506000611bba611fef565b611bc49083612f58565b905060008184611bd2611a0b565b611bdc9190612ff3565b611be6919061300a565b9050611bf1816120ff565b5050505050565b6000611c02611a79565b158015611c8e57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bf86d6906040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c8c9190612fd6565b155b15611cf3576000611c9d611fef565b604080518082019091526002546001600160801b03808216808452600160801b90920416602083015291925090821115611cf057611cf0611ceb8383602001516001600160801b0316612772565b612788565b50505b612710600c54612710611d069190612f58565b611d16611d11611a0b565b6129c0565b611d209190612ff3565b611d2a919061300a565b611d32611fef565b6108aa919061302c565b60005460ff16611d5657506000805460ff19166001179055565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301e1d1146040518163ffffffff1660e01b8152600401602060405180830381865afa158015611db6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dda9190612f29565b905080821115611e4e5760005461271090611dfe90610100900461ffff1683612ff3565b611e08919061300a565b611e128284612f58565b111561138e5760405162461bcd60e51b815260206004820152600b60248201526a6865616c7468436865636b60a81b6044820152606401610747565b8181111561138e5760005461271090611e72906301000000900461ffff1683612ff3565b611e7c919061300a565b611e128383612f58565b60408051608081018252600d546001600160801b038116825265ffffffffffff600160801b820416602083015264ffffffffff600160b01b8204811693830193909352600160d81b90049091166060820152600090611ee3611a79565b158015611f105750806040015164ffffffffff16816060015164ffffffffff1642611f0e9190612f58565b115b8015611f2c575080516001600160801b0316611f2a611fef565b115b8015611f495750600254600160801b90046001600160801b031615155b8015611fd457507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bf86d6906040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190612fd6565b155b15611feb57806020015165ffffffffffff16481091505b5090565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401611a38565b6000811161207d5760405162461bcd60e51b815260206004820152600c60248201526b085e995c9bc81c1c9bd99a5d60a21b6044820152606401610747565b61ffff8111156120bb5760405162461bcd60e51b8152602060048201526009602482015268042e8dede40d0d2ced60bb1b6044820152606401610747565b6000805461ffff9092166101000262ffff0019909216919091179055565b61089d611ceb6120e7611fef565b600254600160801b90046001600160801b0316612772565b60008160000361211157506000919050565b612119611a79565b156121b357600a5460405163339748cb60e01b815273888888888889758f76e7103c6cbf23abbf58f9469163339748cb916121699130916001600160a01b03909116908790600090600401612f6b565b6020604051808303816000875af1158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190612f29565b9150612265565b6121bb612c89565b60008054604051633346d3a360e01b815273888888888889758f76e7103c6cbf23abbf58f94692633346d3a39261220c923092600160281b9092046001600160a01b03169189918890600401613228565b60408051808303816000875af115801561222a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061224e9190613262565b50925060008390036122635750600092915050565b505b60405163769f8e5d60e01b8152306004820152602481018390526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116604483015260006064830181905260848301527f0000000000000000000000000000000000000000000000000000000000000000169063769f8e5d9060a4016020604051808303816000875af1158015612308573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061232c9190612f29565b92915050565b60405162439f4b60e91b81526001600160a01b03838116600483015263ffffffff8316602483015260009182917f0000000000000000000000000000000000000000000000000000000000000000169063873e960090604401606060405180830381865afa1580156123a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123cc9190613286565b925050915081806123db575080155b15610f225760405162461bcd60e51b815260206004820152601060248201526f6f7261636c65206e6f7420726561647960801b6044820152606401610747565b612710811061245a5760405162461bcd60e51b815260206004820152600b60248201526a085b1bdcdcc81b1a5b5a5d60aa1b6044820152606401610747565b6000805461ffff90921663010000000264ffff00000019909216919091179055565b6000612486611a0b565b905080821115612494578091505b600061249f836129c0565b905060006124ac846120ff565b9050612710600b546127106124c19190612f58565b6124cb9084612ff3565b6124d5919061300a565b811015610f225760405162461bcd60e51b81526020600482015260146024820152731d1bdbc81b1a5d1d1b1948185b5bdd5b9d13dd5d60621b6044820152606401610747565b6000806000846001600160a01b03168460405161253891906132cf565b6000604051808303816000865af19150503d8060008114612575576040519150601f19603f3d011682016040523d82523d6000602084013e61257a565b606091505b50915091508180156125a45750805115806125a45750808060200190518101906125a49190612fd6565b80156125b957506001600160a01b0385163b15155b95945050505050565b6000612617826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166119bf9092919063ffffffff16565b90508051600014806126385750808060200190518101906126389190612fd6565b611a065760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610747565b6060824710156126f85760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610747565b600080866001600160a01b0316858760405161271491906132cf565b60006040518083038185875af1925050503d8060008114612751576040519150601f19603f3d011682016040523d82523d6000602084013e612756565b606091505b509150915061276787838387612a64565b979650505050505050565b60008183106127815781610c7b565b5090919050565b6040516320e8c56560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906320e8c565906127fb9030907f0000000000000000000000000000000000000000000000000000000000000000908690600090600401612f6b565b6020604051808303816000875af115801561281a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061283e9190612f29565b506040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156128a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128c79190612f29565b90506128d1612c89565b6000612710600b546127106128e69190612f58565b6128ef85612add565b6128f99190612ff3565b612903919061300a565b600054604051630a94245f60e21b815291925073888888888889758f76e7103c6cbf23abbf58f94691632a50917c91612959913091600160281b90046001600160a01b031690889087906004908a9082016132eb565b60408051808303816000875af1158015612977573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061299b9190613262565b5050600d80546001600160d81b0316600160d81b4264ffffffffff1602179055505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663cbe52ae37f0000000000000000000000000000000000000000000000000000000000000000612a1b85612ba3565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381865afa158015612308573d6000803e3d6000fd5b60608315612ad3578251600003612acc576001600160a01b0385163b612acc5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610747565b50816119ce565b6119ce8383612c5f565b6000805460405163a31426d160e01b8152600160281b82046001600160a01b039081166004830152600160c81b90920463ffffffff1660248201527f00000000000000000000000000000000000000000000000000000000000000009091169063a31426d190604401602060405180830381865afa158015612b63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b879190612f29565b612b99670de0b6b3a764000084612ff3565b61232c919061300a565b6000805460405163a31426d160e01b8152600160281b82046001600160a01b039081166004830152600160c81b90920463ffffffff166024820152670de0b6b3a7640000917f0000000000000000000000000000000000000000000000000000000000000000169063a31426d190604401602060405180830381865afa158015612c31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c559190612f29565b612b999084612ff3565b815115612c6f5781518083602001fd5b8060405162461bcd60e51b81526004016107479190613364565b6040518060a0016040528060006001600160a01b03168152602001600081526020016060815260200160608152602001606081525090565b6001600160a01b038116811461089d57600080fd5b600060208284031215612ce857600080fd5b8135610c7b81612cc1565b80356001600160801b0381168114610c9357600080fd5b600080600060608486031215612d1f57600080fd5b612d2884612cf3565b9250602084013565ffffffffffff81168114612d4357600080fd5b9150604084013564ffffffffff81168114612d5d57600080fd5b809150509250925092565b600060208284031215612d7a57600080fd5b5035919050565b60008060008060808587031215612d9757600080fd5b5050823594602084013594506040840135936060013592509050565b801515811461089d57600080fd5b60008060408385031215612dd457600080fd5b8235612ddf81612cc1565b91506020830135612def81612db3565b809150509250929050565b60005b83811015612e15578181015183820152602001612dfd565b50506000910152565b60008151808452612e36816020860160208601612dfa565b601f01601f19169290920160200192915050565b82151581526040602082015260006119ce6040830184612e1e565b600060208284031215612e7757600080fd5b8135610c7b81612db3565b60008060408385031215612e9557600080fd5b50508035926020909101359150565b60008060408385031215612eb757600080fd5b8235612ec281612cc1565b946020939093013593505050565b600060208284031215612ee257600080fd5b813563ffffffff81168114610c7b57600080fd5b60008060408385031215612f0957600080fd5b612f1283612cf3565b9150612f2060208401612cf3565b90509250929050565b600060208284031215612f3b57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561232c5761232c612f42565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b600080600060608486031215612fa957600080fd5b8351612fb481612cc1565b6020850151909350612fc581612cc1565b6040850151909250612d5d81612cc1565b600060208284031215612fe857600080fd5b8151610c7b81612db3565b808202811582820484141761232c5761232c612f42565b60008261302757634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561232c5761232c612f42565b6004811061305d57634e487b7160e01b600052602160045260246000fd5b9052565b600081518084526020808501808196508360051b8101915082860160005b858110156131b757828403895281516060815181875280518288015287810151608081818a0152604091508183015160a081818c015285850151955060c091506130cb828c018761303f565b91840151945060e0916130e88b8401876001600160a01b03169052565b84015194506101006131048b8201876001600160a01b03169052565b908401519450610120906131228b8301876001600160a01b03169052565b918401519450610140916131408b8401876001600160a01b03169052565b8401516101608b81019190915290840151610180808c0191909152918401516101a08b01528301516101c08a019190915292506131816101e0890184612e1e565b92508884015191508783038989015261319a8383612e1e565b93810151970196909652509885019893509084019060010161307f565b5091979650505050505050565b60018060a01b038151168252602081015160208301526000604082015160a060408501526131f560a0850182613061565b90506060830151848203606086015261320e8282613061565b915050608083015184820360808601526125b98282612e1e565b6001600160a01b03868116825285166020820152604081018490526060810183905260a060808201819052600090612767908301846131c4565b6000806040838503121561327557600080fd5b505080516020909101519092909150565b60008060006060848603121561329b57600080fd5b83516132a681612db3565b602085015190935061ffff811681146132be57600080fd5b6040850151909250612d5d81612db3565b600082516132e1818460208701612dfa565b9190910192915050565b6001600160a01b03878116825286166020820152604081018590526060810184905282546080820152600183015460a0820152600283015460c0820152600383015460e082015260048301546101008201526101406101208201819052600090613357838201856131c4565b9998505050505050505050565b602081526000610c7b6020830184612e1e56fea264697066735822122080aa6f66d3610913017e3c5a184bde24093d96e2dfe9bd5e62ab7b7ce4dbbc9664736f6c6343000812003300000000000000000000000035fa164735182de50811e8e2e824cfb9b6118ac2000000000000000000000000f32e58f92e60f4b0a37a69b95d642a471365eae800000000000000000000000066a1096c6366b2529274df4f5d8247827fe4cea8000000000000000000000000feb4acf3df3cdea7399794d0869ef76a6efaff5200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000217950542d6545544820286175746f2d726f6c6c696e672050656e646c652050542900000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102695760003560e01c80637d96993211610151578063c05bd92d116100c3578063d696860111610087578063d69686011461067d578063d94073d414610690578063ecf70858146106a3578063f462bbff146106ac578063fcfff16f146106bf578063fde813a8146106d357610269565b8063c05bd92d146105ed578063cefba47414610600578063cf683c701461062c578063d19a3bb81461063f578063d63a8e111461065a57610269565b8063a4a7799511610115578063a4a77995146104ff578063ab1c99941461057a578063ac00ff261461058d578063afd27bf5146105a0578063bc06b529146105c7578063bdc8144b146105da57610269565b80637d9699321461049957806380f55605146104ac578063950b3d73146104c65780639d7fb70c146104d9578063a0ef795b146104ec57610269565b80633d6cb575116101ea5780634a5d0943116101ae5780634a5d094314610437578063503160d9146104485780635d265d3f1461045b5780636718835f146104715780636fdca5e01461047e578063797bf3431461049157610269565b80633d6cb575146103e357806345b1993f146103f65780634697f05d1461040957806346aa2f121461041c57806349317f1d1461042f57610269565b80631eab62a9116102315780631eab62a914610365578063256d8a231461036e5780632b24a878146103b05780632f13b60c146103b85780633ba24f81146103d057610269565b806301681a62146102a457806304bd4629146102b757806309b2c8a8146102df5780631809bca51461031d578063180cb47f14610326575b73bb51273d6c746910c7c06fe718f30c936170fed03660008037600080366000845af43d6000803e80801561029d573d6000f35b3d6000fd5b005b6102a26102b2366004612cd6565b6106e6565b6102cc6102c5366004612cd6565b5060001990565b6040519081526020015b60405180910390f35b6002546102fd906001600160801b0380821691600160801b90041682565b604080516001600160801b039384168152929091166020830152016102d6565b6102cc600c5481565b61034d7f000000000000000000000000feb4acf3df3cdea7399794d0869ef76a6efaff5281565b6040516001600160a01b0390911681526020016102d6565b6102cc600b5481565b600454600554600654600754600854610388949392919085565b604080519586526020860194909452928401919091526060830152608082015260a0016102d6565b6102cc6108a0565b6103c06108af565b60405190151581526020016102d6565b6102a26103de366004612d0a565b6108b9565b6102a26103f1366004612d68565b610a6a565b6102a2610404366004612d81565b610a7b565b6102a2610417366004612dc1565b610b06565b6102cc61042a366004612cd6565b610ba8565b6102cc610c98565b600054610100900461ffff166102cc565b6102a2610456366004612d68565b610cb8565b610463610cc0565b6040516102d6929190612e4a565b6000546103c09060ff1681565b6102a261048c366004612e65565b610cfe565b6102cc610d94565b6000546301000000900461ffff166102cc565b60005461034d90600160281b90046001600160a01b031681565b6102a26104d4366004612d68565b610d9e565b6102a26104e7366004612d68565b610e1e565b6102a26104fa366004612e82565b610e2f565b600d5461053c906001600160801b0381169065ffffffffffff600160801b8204169064ffffffffff600160b01b8204811691600160d81b90041684565b604080516001600160801b03909516855265ffffffffffff909316602085015264ffffffffff918216928401929092521660608201526080016102d6565b6102a2610588366004612ea4565b610f28565b6102a261059b366004612e65565b611392565b61034d7f000000000000000000000000ac0047886a985071476a1186be89222659970d6581565b6102a26105d5366004612d68565b61141d565b6102a26105e8366004612d68565b6114a8565b6102a26105fb366004612ed0565b611527565b60005461061790600160c81b900463ffffffff1681565b60405163ffffffff90911681526020016102d6565b6102a261063a366004612d68565b61162c565b61034d73bb51273d6c746910c7c06fe718f30c936170fed081565b6103c0610668366004612cd6565b60016020526000908152604090205460ff1681565b6102a261068b366004612d68565b6116b7565b60095461034d906001600160a01b031681565b6102cc60035481565b6102a26106ba366004612ef6565b611737565b6000546103c090600160e81b900460ff1681565b6102a26106e1366004612d68565b6118dd565b336001600160a01b037f000000000000000000000000feb4acf3df3cdea7399794d0869ef76a6efaff5216146107505760405162461bcd60e51b81526004016107479060208082526004908201526310b3b7bb60e11b604082015260600190565b60405180910390fd5b7f00000000000000000000000035fa164735182de50811e8e2e824cfb9b6118ac26001600160a01b0316816001600160a01b0316036107ba5760405162461bcd60e51b815260206004820152600660248201526508585cdcd95d60d21b6044820152606401610747565b6009546001600160a01b03908116908216036107fe5760405162461bcd60e51b815260206004820152600360248201526208541560ea1b6044820152606401610747565b6040516370a0823160e01b815230600482015261089d907f000000000000000000000000feb4acf3df3cdea7399794d0869ef76a6efaff52906001600160a01b038416906370a0823190602401602060405180830381865afa158015610868573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061088c9190612f29565b6001600160a01b03841691906119d6565b50565b60006108aa611a0b565b905090565b60006108aa611a79565b6040516348e4a64960e01b81523360048201527f0000000000000000000000004d32738401ad45aedcfa17207dba0a14136b10676001600160a01b0316906348e4a6499060240160006040518083038186803b15801561091857600080fd5b505afa15801561092c573d6000803e3d6000fd5b5050505060008164ffffffffff161161097a5760405162461bcd60e51b815260206004820152601060248201526f696e74657276616c20746f6f206c6f7760801b6044820152606401610747565b6001600160801b0383811611156109bf5760405162461bcd60e51b8152602060048201526009602482015268746f6f206c6172676560b81b6044820152606401610747565b6002546001600160801b039081169084161015610a125760405162461bcd60e51b81526020600482015260116024820152701d1c9a59d9d95c881d1bdbc81cdb585b1b607a1b6044820152606401610747565b600d805464ffffffffff909216600160b01b0264ffffffffff60b01b1965ffffffffffff909416600160801b026001600160b01b03199093166001600160801b03909516949094179190911791909116919091179055565b610a72611af1565b61089d81611b2a565b6040516348e4a64960e01b81523360048201527f0000000000000000000000004d32738401ad45aedcfa17207dba0a14136b10676001600160a01b0316906348e4a6499060240160006040518083038186803b158015610ada57600080fd5b505afa158015610aee573d6000803e3d6000fd5b50505060049490945560059290925560075560085550565b6040516348e4a64960e01b81523360048201527f0000000000000000000000004d32738401ad45aedcfa17207dba0a14136b10676001600160a01b0316906348e4a6499060240160006040518083038186803b158015610b6557600080fd5b505afa158015610b79573d6000803e3d6000fd5b505050506001600160a01b03919091166000908152600160205260409020805460ff1916911515919091179055565b6001600160a01b03811660009081526001602052604081205460ff1680610bd85750600054600160e81b900460ff165b15610c8b5760007f0000000000000000000000004d32738401ad45aedcfa17207dba0a14136b10676001600160a01b03166301e1d1146040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c619190612f29565b9050806003541115610c825780600354610c7b9190612f58565b9392505050565b50600092915050565b506000919050565b919050565b6000610ca2611af1565b610caa611bf8565b9050610cb581611d3c565b90565b61089d611af1565b60006060610ccc611e86565b6040805160048152602481019091526020810180516001600160e01b031663440368a360e01b17905290939092509050565b6040516348e4a64960e01b81523360048201527f0000000000000000000000004d32738401ad45aedcfa17207dba0a14136b10676001600160a01b0316906348e4a6499060240160006040518083038186803b158015610d5d57600080fd5b505afa158015610d71573d6000803e3d6000fd5b505060008054931515600160e81b0260ff60e81b19909416939093179092555050565b60006108aa611fef565b6040516348e4a64960e01b81523360048201527f0000000000000000000000004d32738401ad45aedcfa17207dba0a14136b10676001600160a01b0316906348e4a6499060240160006040518083038186803b158015610dfd57600080fd5b505afa158015610e11573d6000803e3d6000fd5b5050505061089d8161203e565b610e26611af1565b61089d816120d9565b6040516320b8029160e21b81523360048201527f0000000000000000000000004d32738401ad45aedcfa17207dba0a14136b10676001600160a01b0316906382e00a449060240160006040518083038186803b158015610e8e57600080fd5b505afa158015610ea2573d6000803e3d6000fd5b5050600280546001600160801b031690555060009050610ec0611a0b565b905080831115610ece578092505b6000610ed9846120ff565b905082811015610f225760405162461bcd60e51b81526020600482015260146024820152731d1bdbc81b1a5d1d1b1948185b5bdd5b9d13dd5d60621b6044820152606401610747565b50505050565b336001600160a01b037f000000000000000000000000feb4acf3df3cdea7399794d0869ef76a6efaff521614610f895760405162461bcd60e51b81526004016107479060208082526004908201526310b3b7bb60e11b604082015260600190565b610f91611a79565b610fcb5760405162461bcd60e51b815260206004820152600b60248201526a1b9bdd08195e1c1a5c995960aa1b6044820152606401610747565b6001600160a01b03821661100b5760405162461bcd60e51b8152602060048201526007602482015266085b585c9ad95d60ca1b6044820152606401610747565b6000546001600160a01b03808416600160281b909204160361105d5760405162461bcd60e51b815260206004820152600b60248201526a1cd85b59481b585c9ad95d60aa1b6044820152606401610747565b600054611078908390600160c81b900463ffffffff16612332565b6000611082611a0b565b9050801561111b57600a5460405163339748cb60e01b815273888888888889758f76e7103c6cbf23abbf58f9469163339748cb916110d59130916001600160a01b03909116908690600090600401612f6b565b6020604051808303816000875af11580156110f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111189190612f29565b90505b6000805465010000000000600160c81b031916600160281b6001600160a01b03861602179055611149611a79565b156111805760405162461bcd60e51b8152602060048201526007602482015266195e1c1a5c995960ca1b6044820152606401610747565b6000806000856001600160a01b0316632c8ce6bc6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156111c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e79190612f94565b9250925092507f000000000000000000000000ac0047886a985071476a1186be89222659970d656001600160a01b0316836001600160a01b0316146112595760405162461bcd60e51b815260206004820152600860248201526777726f6e6720535960c01b6044820152606401610747565b600980546001600160a01b038085166001600160a01b03199283168117909355600a8054918516919092161790556112a89073888888888889758f76e7103c6cbf23abbf58f9466000196118ee565b831580156112b4575084155b156112c157505050505050565b60405163769f8e5d60e01b8152306004820152602481018590526001600160a01b037f00000000000000000000000035fa164735182de50811e8e2e824cfb9b6118ac28116604483015260648201879052600060848301527f000000000000000000000000ac0047886a985071476a1186be89222659970d65169063769f8e5d9060a4016020604051808303816000875af1158015611364573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113889190612f29565b50505050505b5050565b6040516348e4a64960e01b81523360048201527f0000000000000000000000004d32738401ad45aedcfa17207dba0a14136b10676001600160a01b0316906348e4a6499060240160006040518083038186803b1580156113f157600080fd5b505afa158015611405573d6000803e3d6000fd5b50506000805460ff1916931515939093179092555050565b6040516348e4a64960e01b81523360048201527f0000000000000000000000004d32738401ad45aedcfa17207dba0a14136b10676001600160a01b0316906348e4a6499060240160006040518083038186803b15801561147c57600080fd5b505afa158015611490573d6000803e3d6000fd5b505050506127108111156114a357600080fd5b600c55565b6040516348e4a64960e01b81523360048201527f0000000000000000000000004d32738401ad45aedcfa17207dba0a14136b10676001600160a01b0316906348e4a6499060240160006040518083038186803b15801561150757600080fd5b505afa15801561151b573d6000803e3d6000fd5b50505060039190915550565b6040516320b8029160e21b81523360048201527f0000000000000000000000004d32738401ad45aedcfa17207dba0a14136b10676001600160a01b0316906382e00a449060240160006040518083038186803b15801561158657600080fd5b505afa15801561159a573d6000803e3d6000fd5b505050506103848163ffffffff1610156115e95760405162461bcd60e51b815260206004820152601060248201526f6475726174696f6e20746f6f206c6f7760801b6044820152606401610747565b60005461160690600160281b90046001600160a01b031682612332565b6000805463ffffffff909216600160c81b0263ffffffff60c81b19909216919091179055565b6040516348e4a64960e01b81523360048201527f0000000000000000000000004d32738401ad45aedcfa17207dba0a14136b10676001600160a01b0316906348e4a6499060240160006040518083038186803b15801561168b57600080fd5b505afa15801561169f573d6000803e3d6000fd5b505050506127108111156116b257600080fd5b600b55565b6040516348e4a64960e01b81523360048201527f0000000000000000000000004d32738401ad45aedcfa17207dba0a14136b10676001600160a01b0316906348e4a6499060240160006040518083038186803b15801561171657600080fd5b505afa15801561172a573d6000803e3d6000fd5b5050505061089d8161241b565b6040516348e4a64960e01b81523360048201527f0000000000000000000000004d32738401ad45aedcfa17207dba0a14136b10676001600160a01b0316906348e4a6499060240160006040518083038186803b15801561179657600080fd5b505afa1580156117aa573d6000803e3d6000fd5b5050506001600160801b0382811611801591506117d057506001600160801b0382811611155b6118085760405162461bcd60e51b8152602060048201526009602482015268746f6f206c6172676560b81b6044820152606401610747565b816001600160801b0316816001600160801b031610156118585760405162461bcd60e51b815260206004820152600b60248201526a3bb937b7339037b93232b960a91b6044820152606401610747565b600d546001600160801b03808416911610156118ab5760405162461bcd60e51b81526020600482015260126024820152716d696e417373657420746f6f206c6172676560701b6044820152606401610747565b604080518082019091526001600160801b03928316808252919092166020909201829052600160801b90910217600255565b6118e5611af1565b61089d8161247c565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261193f848261251b565b610f22576040516001600160a01b0384166024820152600060448201526119a690859063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526125c2565b610f2284826125c2565b6001600160a01b03163b151590565b60606119ce8484600085612697565b949350505050565b6040516001600160a01b038316602482015260448101829052611a0690849063a9059cbb60e01b9060640161196f565b505050565b6009546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a08231906024015b602060405180830381865afa158015611a55573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108aa9190612f29565b60008060059054906101000a90046001600160a01b03166001600160a01b0316632f13b60c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611acd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108aa9190612fd6565b333014611b285760405162461bcd60e51b815260206004820152600560248201526410b9b2b63360d91b6044820152606401610747565b565b60007f0000000000000000000000004d32738401ad45aedcfa17207dba0a14136b10676001600160a01b03166301e1d1146040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bae9190612f29565b90506000611bba611fef565b611bc49083612f58565b905060008184611bd2611a0b565b611bdc9190612ff3565b611be6919061300a565b9050611bf1816120ff565b5050505050565b6000611c02611a79565b158015611c8e57507f0000000000000000000000004d32738401ad45aedcfa17207dba0a14136b10676001600160a01b031663bf86d6906040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c8c9190612fd6565b155b15611cf3576000611c9d611fef565b604080518082019091526002546001600160801b03808216808452600160801b90920416602083015291925090821115611cf057611cf0611ceb8383602001516001600160801b0316612772565b612788565b50505b612710600c54612710611d069190612f58565b611d16611d11611a0b565b6129c0565b611d209190612ff3565b611d2a919061300a565b611d32611fef565b6108aa919061302c565b60005460ff16611d5657506000805460ff19166001179055565b60007f0000000000000000000000004d32738401ad45aedcfa17207dba0a14136b10676001600160a01b03166301e1d1146040518163ffffffff1660e01b8152600401602060405180830381865afa158015611db6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dda9190612f29565b905080821115611e4e5760005461271090611dfe90610100900461ffff1683612ff3565b611e08919061300a565b611e128284612f58565b111561138e5760405162461bcd60e51b815260206004820152600b60248201526a6865616c7468436865636b60a81b6044820152606401610747565b8181111561138e5760005461271090611e72906301000000900461ffff1683612ff3565b611e7c919061300a565b611e128383612f58565b60408051608081018252600d546001600160801b038116825265ffffffffffff600160801b820416602083015264ffffffffff600160b01b8204811693830193909352600160d81b90049091166060820152600090611ee3611a79565b158015611f105750806040015164ffffffffff16816060015164ffffffffff1642611f0e9190612f58565b115b8015611f2c575080516001600160801b0316611f2a611fef565b115b8015611f495750600254600160801b90046001600160801b031615155b8015611fd457507f0000000000000000000000004d32738401ad45aedcfa17207dba0a14136b10676001600160a01b031663bf86d6906040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd29190612fd6565b155b15611feb57806020015165ffffffffffff16481091505b5090565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000035fa164735182de50811e8e2e824cfb9b6118ac26001600160a01b0316906370a0823190602401611a38565b6000811161207d5760405162461bcd60e51b815260206004820152600c60248201526b085e995c9bc81c1c9bd99a5d60a21b6044820152606401610747565b61ffff8111156120bb5760405162461bcd60e51b8152602060048201526009602482015268042e8dede40d0d2ced60bb1b6044820152606401610747565b6000805461ffff9092166101000262ffff0019909216919091179055565b61089d611ceb6120e7611fef565b600254600160801b90046001600160801b0316612772565b60008160000361211157506000919050565b612119611a79565b156121b357600a5460405163339748cb60e01b815273888888888889758f76e7103c6cbf23abbf58f9469163339748cb916121699130916001600160a01b03909116908790600090600401612f6b565b6020604051808303816000875af1158015612188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ac9190612f29565b9150612265565b6121bb612c89565b60008054604051633346d3a360e01b815273888888888889758f76e7103c6cbf23abbf58f94692633346d3a39261220c923092600160281b9092046001600160a01b03169189918890600401613228565b60408051808303816000875af115801561222a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061224e9190613262565b50925060008390036122635750600092915050565b505b60405163769f8e5d60e01b8152306004820152602481018390526001600160a01b037f00000000000000000000000035fa164735182de50811e8e2e824cfb9b6118ac28116604483015260006064830181905260848301527f000000000000000000000000ac0047886a985071476a1186be89222659970d65169063769f8e5d9060a4016020604051808303816000875af1158015612308573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061232c9190612f29565b92915050565b60405162439f4b60e91b81526001600160a01b03838116600483015263ffffffff8316602483015260009182917f00000000000000000000000066a1096c6366b2529274df4f5d8247827fe4cea8169063873e960090604401606060405180830381865afa1580156123a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123cc9190613286565b925050915081806123db575080155b15610f225760405162461bcd60e51b815260206004820152601060248201526f6f7261636c65206e6f7420726561647960801b6044820152606401610747565b612710811061245a5760405162461bcd60e51b815260206004820152600b60248201526a085b1bdcdcc81b1a5b5a5d60aa1b6044820152606401610747565b6000805461ffff90921663010000000264ffff00000019909216919091179055565b6000612486611a0b565b905080821115612494578091505b600061249f836129c0565b905060006124ac846120ff565b9050612710600b546127106124c19190612f58565b6124cb9084612ff3565b6124d5919061300a565b811015610f225760405162461bcd60e51b81526020600482015260146024820152731d1bdbc81b1a5d1d1b1948185b5bdd5b9d13dd5d60621b6044820152606401610747565b6000806000846001600160a01b03168460405161253891906132cf565b6000604051808303816000865af19150503d8060008114612575576040519150601f19603f3d011682016040523d82523d6000602084013e61257a565b606091505b50915091508180156125a45750805115806125a45750808060200190518101906125a49190612fd6565b80156125b957506001600160a01b0385163b15155b95945050505050565b6000612617826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166119bf9092919063ffffffff16565b90508051600014806126385750808060200190518101906126389190612fd6565b611a065760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610747565b6060824710156126f85760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610747565b600080866001600160a01b0316858760405161271491906132cf565b60006040518083038185875af1925050503d8060008114612751576040519150601f19603f3d011682016040523d82523d6000602084013e612756565b606091505b509150915061276787838387612a64565b979650505050505050565b60008183106127815781610c7b565b5090919050565b6040516320e8c56560e01b81526001600160a01b037f000000000000000000000000ac0047886a985071476a1186be89222659970d6516906320e8c565906127fb9030907f00000000000000000000000035fa164735182de50811e8e2e824cfb9b6118ac2908690600090600401612f6b565b6020604051808303816000875af115801561281a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061283e9190612f29565b506040516370a0823160e01b81523060048201527f000000000000000000000000ac0047886a985071476a1186be89222659970d656001600160a01b0316906370a0823190602401602060405180830381865afa1580156128a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128c79190612f29565b90506128d1612c89565b6000612710600b546127106128e69190612f58565b6128ef85612add565b6128f99190612ff3565b612903919061300a565b600054604051630a94245f60e21b815291925073888888888889758f76e7103c6cbf23abbf58f94691632a50917c91612959913091600160281b90046001600160a01b031690889087906004908a9082016132eb565b60408051808303816000875af1158015612977573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061299b9190613262565b5050600d80546001600160d81b0316600160d81b4264ffffffffff1602179055505050565b60007f000000000000000000000000ac0047886a985071476a1186be89222659970d656001600160a01b031663cbe52ae37f00000000000000000000000035fa164735182de50811e8e2e824cfb9b6118ac2612a1b85612ba3565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381865afa158015612308573d6000803e3d6000fd5b60608315612ad3578251600003612acc576001600160a01b0385163b612acc5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610747565b50816119ce565b6119ce8383612c5f565b6000805460405163a31426d160e01b8152600160281b82046001600160a01b039081166004830152600160c81b90920463ffffffff1660248201527f00000000000000000000000066a1096c6366b2529274df4f5d8247827fe4cea89091169063a31426d190604401602060405180830381865afa158015612b63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b879190612f29565b612b99670de0b6b3a764000084612ff3565b61232c919061300a565b6000805460405163a31426d160e01b8152600160281b82046001600160a01b039081166004830152600160c81b90920463ffffffff166024820152670de0b6b3a7640000917f00000000000000000000000066a1096c6366b2529274df4f5d8247827fe4cea8169063a31426d190604401602060405180830381865afa158015612c31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c559190612f29565b612b999084612ff3565b815115612c6f5781518083602001fd5b8060405162461bcd60e51b81526004016107479190613364565b6040518060a0016040528060006001600160a01b03168152602001600081526020016060815260200160608152602001606081525090565b6001600160a01b038116811461089d57600080fd5b600060208284031215612ce857600080fd5b8135610c7b81612cc1565b80356001600160801b0381168114610c9357600080fd5b600080600060608486031215612d1f57600080fd5b612d2884612cf3565b9250602084013565ffffffffffff81168114612d4357600080fd5b9150604084013564ffffffffff81168114612d5d57600080fd5b809150509250925092565b600060208284031215612d7a57600080fd5b5035919050565b60008060008060808587031215612d9757600080fd5b5050823594602084013594506040840135936060013592509050565b801515811461089d57600080fd5b60008060408385031215612dd457600080fd5b8235612ddf81612cc1565b91506020830135612def81612db3565b809150509250929050565b60005b83811015612e15578181015183820152602001612dfd565b50506000910152565b60008151808452612e36816020860160208601612dfa565b601f01601f19169290920160200192915050565b82151581526040602082015260006119ce6040830184612e1e565b600060208284031215612e7757600080fd5b8135610c7b81612db3565b60008060408385031215612e9557600080fd5b50508035926020909101359150565b60008060408385031215612eb757600080fd5b8235612ec281612cc1565b946020939093013593505050565b600060208284031215612ee257600080fd5b813563ffffffff81168114610c7b57600080fd5b60008060408385031215612f0957600080fd5b612f1283612cf3565b9150612f2060208401612cf3565b90509250929050565b600060208284031215612f3b57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561232c5761232c612f42565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b600080600060608486031215612fa957600080fd5b8351612fb481612cc1565b6020850151909350612fc581612cc1565b6040850151909250612d5d81612cc1565b600060208284031215612fe857600080fd5b8151610c7b81612db3565b808202811582820484141761232c5761232c612f42565b60008261302757634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561232c5761232c612f42565b6004811061305d57634e487b7160e01b600052602160045260246000fd5b9052565b600081518084526020808501808196508360051b8101915082860160005b858110156131b757828403895281516060815181875280518288015287810151608081818a0152604091508183015160a081818c015285850151955060c091506130cb828c018761303f565b91840151945060e0916130e88b8401876001600160a01b03169052565b84015194506101006131048b8201876001600160a01b03169052565b908401519450610120906131228b8301876001600160a01b03169052565b918401519450610140916131408b8401876001600160a01b03169052565b8401516101608b81019190915290840151610180808c0191909152918401516101a08b01528301516101c08a019190915292506131816101e0890184612e1e565b92508884015191508783038989015261319a8383612e1e565b93810151970196909652509885019893509084019060010161307f565b5091979650505050505050565b60018060a01b038151168252602081015160208301526000604082015160a060408501526131f560a0850182613061565b90506060830151848203606086015261320e8282613061565b915050608083015184820360808601526125b98282612e1e565b6001600160a01b03868116825285166020820152604081018490526060810183905260a060808201819052600090612767908301846131c4565b6000806040838503121561327557600080fd5b505080516020909101519092909150565b60008060006060848603121561329b57600080fd5b83516132a681612db3565b602085015190935061ffff811681146132be57600080fd5b6040850151909250612d5d81612db3565b600082516132e1818460208701612dfa565b9190910192915050565b6001600160a01b03878116825286166020820152604081018590526060810184905282546080820152600183015460a0820152600283015460c0820152600383015460e082015260048301546101008201526101406101208201819052600090613357838201856131c4565b9998505050505050505050565b602081526000610c7b6020830184612e1e56fea264697066735822122080aa6f66d3610913017e3c5a184bde24093d96e2dfe9bd5e62ab7b7ce4dbbc9664736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000035fa164735182de50811e8e2e824cfb9b6118ac2000000000000000000000000f32e58f92e60f4b0a37a69b95d642a471365eae800000000000000000000000066a1096c6366b2529274df4f5d8247827fe4cea8000000000000000000000000feb4acf3df3cdea7399794d0869ef76a6efaff5200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000217950542d6545544820286175746f2d726f6c6c696e672050656e646c652050542900000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _asset (address): 0x35fA164735182de50811E8e2E824cFb9B6118ac2
Arg [1] : _market (address): 0xF32e58F92e60f4b0A37A69b95d642A471365EAe8
Arg [2] : _oracle (address): 0x66a1096C6366b2529274dF4f5D8247827fe4CEA8
Arg [3] : _GOV (address): 0xFEB4acf3df3cDEA7399794D0869ef76A6EfAff52
Arg [4] : _name (string): yPT-eETH (auto-rolling Pendle PT)
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 00000000000000000000000035fa164735182de50811e8e2e824cfb9b6118ac2
Arg [1] : 000000000000000000000000f32e58f92e60f4b0a37a69b95d642a471365eae8
Arg [2] : 00000000000000000000000066a1096c6366b2529274df4f5d8247827fe4cea8
Arg [3] : 000000000000000000000000feb4acf3df3cdea7399794d0869ef76a6efaff52
Arg [4] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000021
Arg [6] : 7950542d6545544820286175746f2d726f6c6c696e672050656e646c65205054
Arg [7] : 2900000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
84227:20488:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42278:42;58123:14;57872:33;;58104:34;58385:1;58365;58332:14;58312:1;58268:25;58244:5;58213:188;58473:16;58470:1;58467;58452:38;58579:6;58599:68;;;;58718:16;58715:1;58708:27;58599:68;58635:16;58632:1;58625:27;58572:178;;104375:238;;;;;;:::i;:::-;;:::i;51611:149::-;;;;;;:::i;:::-;-1:-1:-1;;;51735:17:0;51611:149;;;;548:25:1;;;536:2;521:18;51611:149:0;;;;;;;;85103:30;;;;;-1:-1:-1;;;;;85103:30:0;;;;-1:-1:-1;;;85103:30:0;;;;;;;;;-1:-1:-1;;;;;829:15:1;;;811:34;;881:15;;;;876:2;861:18;;854:43;731:18;85103:30:0;584:319:1;85984:32:0;;;;;;86697:28;;;;;;;;-1:-1:-1;;;;;1181:32:1;;;1163:51;;1151:2;1136:18;86697:28:0;1017:203:1;85811:30:0;;;;;;85489:46;;;;;;;;;;;;;;;;;;;;;;;1484:25:1;;;1540:2;1525:18;;1518:34;;;;1568:18;;;1561:34;;;;1626:2;1611:18;;1604:34;1669:3;1654:19;;1647:35;1471:3;1456:19;85489:46:0;1225:463:1;95086:95:0;;;:::i;95189:88::-;;;:::i;:::-;;;1858:14:1;;1851:22;1833:41;;1821:2;1806:18;95189:88:0;1693:187:1;98431:586:0;;;;;;:::i;:::-;;:::i;54158:100::-;;;;;;:::i;:::-;;:::i;97549:506::-;;;;;;:::i;:::-;;:::i;100649:149::-;;;;;;:::i;:::-;;:::i;93376:504::-;;;;;;:::i;:::-;;:::i;62754:319::-;;;:::i;60320:101::-;60369:7;60396:17;;;;;;60320:101;;53574:104;;;;;;:::i;:::-;;:::i;49309:318::-;;;:::i;:::-;;;;;;;;:::i;59757:32::-;;;;;;;;;100324:84;;;;;;:::i;:::-;;:::i;94977:101::-;;;:::i;60614:97::-;60661:7;60688:15;;;;;;60614:97;;84360:21;;;;;-1:-1:-1;;;84360:21:0;;-1:-1:-1;;;;;84360:21:0;;;60906:160;;;;;;:::i;:::-;;:::i;55477:100::-;;;;;;:::i;:::-;;:::i;101290:453::-;;;;;;:::i;:::-;;:::i;86613:42::-;;;;;-1:-1:-1;;;;;86613:42:0;;;;-1:-1:-1;;;86613:42:0;;;;;-1:-1:-1;;;86613:42:0;;;;;-1:-1:-1;;;86613:42:0;;;;;;;;;-1:-1:-1;;;;;5271:47:1;;;5253:66;;5367:14;5355:27;;;5350:2;5335:18;;5328:55;5402:12;5450:15;;;5430:18;;;5423:43;;;;5502:15;5497:2;5482:18;;5475:43;5240:3;5225:19;86613:42:0;5028:496:1;102811:1412:0;;;;;;:::i;:::-;;:::i;62469:118::-;;;;;;:::i;:::-;;:::i;85595:27::-;;;;;99909:204;;;;;;:::i;:::-;;:::i;99196:119::-;;;;;;:::i;:::-;;:::i;95411:261::-;;;;;;:::i;:::-;;:::i;84480:28::-;;;;;-1:-1:-1;;;84480:28:0;;;;;;;;;6304:10:1;6292:23;;;6274:42;;6262:2;6247:18;84480:28:0;6130:192:1;99489:194:0;;;;;;:::i;:::-;;:::i;42218:102::-;;42278:42;42218:102;;84687:39;;;;;;:::i;:::-;;;;;;;;;;;;;;;;61722:152;;;;;;:::i;:::-;;:::i;85682:17::-;;;;;-1:-1:-1;;;;;85682:17:0;;;85245:47;;;;;;96136:671;;;;;;:::i;:::-;;:::i;84598:23::-;;;;;-1:-1:-1;;;84598:23:0;;;;;;56106:115;;;;;;:::i;:::-;;:::i;104375:238::-;104666:10;-1:-1:-1;;;;;104680:3:0;104666:17;;104658:34;;;;-1:-1:-1;;;104658:34:0;;;;;;6794:2:1;6776:21;;;6833:1;6813:18;;;6806:29;-1:-1:-1;;;6866:2:1;6851:18;;6844:34;6910:2;6895:18;;6592:327;104658:34:0;;;;;;;;;104467:5:::1;-1:-1:-1::0;;;;;104449:24:0::1;:6;-1:-1:-1::0;;;;;104449:24:0::1;::::0;104441:43:::1;;;::::0;-1:-1:-1;;;104441:43:0;;7126:2:1;104441:43:0::1;::::0;::::1;7108:21:1::0;7165:1;7145:18;;;7138:29;-1:-1:-1;;;7183:18:1;;;7176:36;7229:18;;104441:43:0::1;6924:329:1::0;104441:43:0::1;104513:2;::::0;-1:-1:-1;;;;;104513:2:0;;::::1;104503:12:::0;;::::1;::::0;104495:28:::1;;;::::0;-1:-1:-1;;;104495:28:0;;7460:2:1;104495:28:0::1;::::0;::::1;7442:21:1::0;7499:1;7479:18;;;7472:29;-1:-1:-1;;;7517:18:1;;;7510:33;7560:18;;104495:28:0::1;7258:326:1::0;104495:28:0::1;104566:38;::::0;-1:-1:-1;;;104566:38:0;;104598:4:::1;104566:38;::::0;::::1;1163:51:1::0;104534:71:0::1;::::0;104561:3:::1;::::0;-1:-1:-1;;;;;104566:23:0;::::1;::::0;::::1;::::0;1136:18:1;;104566:38:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;104534:26:0;::::1;::::0;:71;:26:::1;:71::i;:::-;104375:238:::0;:::o;95086:95::-;95132:7;95159:14;:12;:14::i;:::-;95152:21;;95086:95;:::o;95189:88::-;95233:4;95257:12;:10;:12::i;98431:586::-;40679:47;;-1:-1:-1;;;40679:47:0;;40715:10;40679:47;;;1163:51:1;40679:17:0;-1:-1:-1;;;;;40679:35:0;;;;1136:18:1;;40679:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;98637:1:::1;98615:19;:23;;;98607:52;;;::::0;-1:-1:-1;;;98607:52:0;;7980:2:1;98607:52:0::1;::::0;::::1;7962:21:1::0;8019:2;7999:18;;;7992:30;-1:-1:-1;;;8038:18:1;;;8031:46;8094:18;;98607:52:0::1;7778:340:1::0;98607:52:0::1;-1:-1:-1::0;;;;;98678:36:0;;::::1;;;98670:58;;;::::0;-1:-1:-1;;;98670:58:0;;8325:2:1;98670:58:0::1;::::0;::::1;8307:21:1::0;8364:1;8344:18;;;8337:29;-1:-1:-1;;;8382:18:1;;;8375:39;8431:18;;98670:58:0::1;8123:332:1::0;98670:58:0::1;98766:11;:30:::0;-1:-1:-1;;;;;98766:30:0;;::::1;98747:49:::0;;::::1;;;98739:79;;;::::0;-1:-1:-1;;;98739:79:0;;8662:2:1;98739:79:0::1;::::0;::::1;8644:21:1::0;8701:2;8681:18;;;8674:30;-1:-1:-1;;;8720:18:1;;;8713:47;8777:18;;98739:79:0::1;8460:341:1::0;98739:79:0::1;98829:17;:50:::0;;98951:58:::1;::::0;;::::1;-1:-1:-1::0;;;98951:58:0::1;-1:-1:-1::0;;;;98890:50:0::1;::::0;;::::1;-1:-1:-1::0;;;98890:50:0::1;-1:-1:-1::0;;;;;;98890:50:0;;;-1:-1:-1;;;;;98829:50:0;;::::1;98890::::0;;;;;;;::::1;98951:58:::0;;;::::1;::::0;;;::::1;::::0;;98431:586::o;54158:100::-;40502:11;:9;:11::i;:::-;54231:19:::1;54242:7;54231:10;:19::i;97549:506::-:0;40679:47;;-1:-1:-1;;;40679:47:0;;40715:10;40679:47;;;1163:51:1;40679:17:0;-1:-1:-1;;;;;40679:35:0;;;;1136:18:1;;40679:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;97727:12:0::1;:33:::0;;;;97785:21;:33;;;;97859:25;:41;97927:16;:23;-1:-1:-1;97549:506:0:o;100649:149::-;40679:47;;-1:-1:-1;;;40679:47:0;;40715:10;40679:47;;;1163:51:1;40679:17:0;-1:-1:-1;;;;;40679:35:0;;;;1136:18:1;;40679:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;100762:17:0;;;::::1;;::::0;;;:7:::1;:17;::::0;;;;:28;;-1:-1:-1;;100762:28:0::1;::::0;::::1;;::::0;;;::::1;::::0;;100649:149::o;93376:504::-;-1:-1:-1;;;;;93558:15:0;;93469:7;93558:15;;;:7;:15;;;;;;;;;:23;;-1:-1:-1;93577:4:0;;-1:-1:-1;;;93577:4:0;;;;93558:23;93554:319;;;93598:21;93622:17;-1:-1:-1;;;;;93622:29:0;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93598:55;;93687:13;93672:12;;:28;93668:153;;;93743:13;93728:12;;:28;;;;:::i;:::-;93721:35;93376:504;-1:-1:-1;;;93376:504:0:o;93668:153::-;-1:-1:-1;93804:1:0;;93376:504;-1:-1:-1;;93376:504:0:o;93554:319::-;-1:-1:-1;93860:1:0;;93376:504;-1:-1:-1;93376:504:0:o;93554:319::-;93376:504;;;:::o;62754:319::-;62854:20;40502:11;:9;:11::i;:::-;62944:19:::1;:17;:19::i;:::-;62929:34;;63032:33;63052:12;63032:19;:33::i;:::-;62754:319:::0;:::o;53574:104::-;40502:11;:9;:11::i;49309:318::-;49363:4;49369:12;49471:14;:12;:14::i;:::-;49552:56;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;49552:56:0;-1:-1:-1;;;49552:56:0;;;49394:225;;49552:56;;-1:-1:-1;49309:318:0;-1:-1:-1;49309:318:0:o;100324:84::-;40679:47;;-1:-1:-1;;;40679:47:0;;40715:10;40679:47;;;1163:51:1;40679:17:0;-1:-1:-1;;;;;40679:35:0;;;;1136:18:1;;40679:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;100388:4:0::1;:12:::0;;;::::1;;-1:-1:-1::0;;;100388:12:0::1;-1:-1:-1::0;;;;100388:12:0;;::::1;::::0;;;::::1;::::0;;;-1:-1:-1;;100324:84:0:o;94977:101::-;95026:7;95053:17;:15;:17::i;60906:160::-;40679:47;;-1:-1:-1;;;40679:47:0;;40715:10;40679:47;;;1163:51:1;40679:17:0;-1:-1:-1;;;;;40679:35:0;;;;1136:18:1;;40679:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61016:42:::1;61037:20;61016;:42::i;55477:100::-:0;40502:11;:9;:11::i;:::-;55552:17:::1;55558:10;55552:5;:17::i;101290:453::-:0;41186:56;;-1:-1:-1;;;41186:56:0;;41231:10;41186:56;;;1163:51:1;41186:17:0;-1:-1:-1;;;;;41186:44:0;;;;1136:18:1;;41186:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;101433:11:0::1;:30:::0;;-1:-1:-1;;;;;101433:30:0::1;::::0;;-1:-1:-1;101462:1:0::1;::::0;-1:-1:-1;101499:14:0::1;:12;:14::i;:::-;101474:39;;101538:14;101528:7;:24;101524:81;;;101579:14;101569:24;;101524:81;101615:18;101636;101646:7;101636:9;:18::i;:::-;101615:39;;101687:23;101673:10;:37;;101665:70;;;::::0;-1:-1:-1;;;101665:70:0;;9273:2:1;101665:70:0::1;::::0;::::1;9255:21:1::0;9312:2;9292:18;;;9285:30;-1:-1:-1;;;9331:18:1;;;9324:50;9391:18;;101665:70:0::1;9071:344:1::0;101665:70:0::1;101422:321;;101290:453:::0;;:::o;102811:1412::-;104666:10;-1:-1:-1;;;;;104680:3:0;104666:17;;104658:34;;;;-1:-1:-1;;;104658:34:0;;;;;;6794:2:1;6776:21;;;6833:1;6813:18;;;6806:29;-1:-1:-1;;;6866:2:1;6851:18;;6844:34;6910:2;6895:18;;6592:327;104658:34:0;102950:12:::1;:10;:12::i;:::-;102942:36;;;::::0;-1:-1:-1;;;102942:36:0;;9622:2:1;102942:36:0::1;::::0;::::1;9604:21:1::0;9661:2;9641:18;;;9634:30;-1:-1:-1;;;9680:18:1;;;9673:41;9731:18;;102942:36:0::1;9420:335:1::0;102942:36:0::1;-1:-1:-1::0;;;;;102997:21:0;::::1;102989:41;;;::::0;-1:-1:-1;;;102989:41:0;;9962:2:1;102989:41:0::1;::::0;::::1;9944:21:1::0;10001:1;9981:18;;;9974:29;-1:-1:-1;;;10019:18:1;;;10012:37;10066:18;;102989:41:0::1;9760:330:1::0;102989:41:0::1;103049:6;::::0;-1:-1:-1;;;;;103049:17:0;;::::1;-1:-1:-1::0;;;103049:6:0;;::::1;;:17:::0;103041:41:::1;;;::::0;-1:-1:-1;;;103041:41:0;;10297:2:1;103041:41:0::1;::::0;::::1;10279:21:1::0;10336:2;10316:18;;;10309:30;-1:-1:-1;;;10355:18:1;;;10348:41;10406:18;;103041:41:0::1;10095:335:1::0;103041:41:0::1;103190:14;::::0;103168:37:::1;::::0;103181:7;;-1:-1:-1;;;103190:14:0;::::1;;;103168:12;:37::i;:::-;103249:22;103274:14;:12;:14::i;:::-;103249:39:::0;-1:-1:-1;103303:18:0;;103299:229:::1;;103446:2;::::0;103355:161:::1;::::0;-1:-1:-1;;;103355:161:0;;85351:42:::1;::::0;103355:40:::1;::::0;:161:::1;::::0;103422:4:::1;::::0;-1:-1:-1;;;;;103446:2:0;;::::1;::::0;103467:14;;103446:2:::1;::::0;103355:161:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;103338:178;;103299:229;103581:6;:16:::0;;-1:-1:-1;;;;;;103581:16:0::1;-1:-1:-1::0;;;;;;;;103581:16:0;::::1;;;::::0;;103617:12:::1;:10;:12::i;:::-;103616:13;103608:33;;;::::0;-1:-1:-1;;;103608:33:0;;11097:2:1;103608:33:0::1;::::0;::::1;11079:21:1::0;11136:1;11116:18;;;11109:29;-1:-1:-1;;;11154:18:1;;;11147:37;11201:18;;103608:33:0::1;10895:330:1::0;103608:33:0::1;103653:11;103666::::0;103679::::1;103708:7;-1:-1:-1::0;;;;;103694:47:0::1;;:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;103652:91;;;;;;103769:2;-1:-1:-1::0;;;;;103762:9:0::1;:3;-1:-1:-1::0;;;;;103762:9:0::1;;103754:30;;;::::0;-1:-1:-1;;;103754:30:0;;11956:2:1;103754:30:0::1;::::0;::::1;11938:21:1::0;11995:1;11975:18;;;11968:29;-1:-1:-1;;;12013:18:1;;;12006:38;12061:18;;103754:30:0::1;11754:331:1::0;103754:30:0::1;103795:2;:8:::0;;-1:-1:-1;;;;;103795:8:0;;::::1;-1:-1:-1::0;;;;;;103795:8:0;;::::1;::::0;::::1;::::0;;;103814:2:::1;:8:::0;;;;::::1;::::0;;;::::1;;::::0;;103833:56:::1;::::0;85351:42:::1;-1:-1:-1::0;;103833:23:0::1;:56::i;:::-;103986:19:::0;;:46;::::1;;;-1:-1:-1::0;104009:23:0;;103986:46:::1;103982:59;;;104034:7;;;;102811:1412:::0;;:::o;103982:59::-:1;104051:164;::::0;-1:-1:-1;;;104051:164:0;;104088:4:::1;104051:164;::::0;::::1;12381:34:1::0;12431:18;;;12424:34;;;-1:-1:-1;;;;;104145:5:0::1;12494:15:1::0;;12474:18;;;12467:43;12526:18;;;12519:34;;;-1:-1:-1;12569:19:1;;;12562:51;104055:2:0::1;104051:14;::::0;::::1;::::0;12315:19:1;;104051:164:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;102931:1292;;;;104703:1;102811:1412:::0;;:::o;62469:118::-;40679:47;;-1:-1:-1;;;40679:47:0;;40715:10;40679:47;;;1163:51:1;40679:17:0;-1:-1:-1;;;;;40679:35:0;;;;1136:18:1;;40679:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;62549:13:0::1;:30:::0;;-1:-1:-1;;62549:30:0::1;::::0;::::1;;::::0;;;::::1;::::0;;;-1:-1:-1;;62469:118:0:o;99909:204::-;40679:47;;-1:-1:-1;;;40679:47:0;;40715:10;40679:47;;;1163:51:1;40679:17:0;-1:-1:-1;;;;;40679:35:0;;;;1136:18:1;;40679:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59834:6:::1;100026:18;:29;;100018:38;;;::::0;::::1;;100067:17;:38:::0;99909:204::o;99196:119::-;40679:47;;-1:-1:-1;;;40679:47:0;;40715:10;40679:47;;;1163:51:1;40679:17:0;-1:-1:-1;;;;;40679:35:0;;;;1136:18:1;;40679:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;99279:12:0::1;:28:::0;;;;-1:-1:-1;99196:119:0:o;95411:261::-;41186:56;;-1:-1:-1;;;41186:56:0;;41231:10;41186:56;;;1163:51:1;41186:17:0;-1:-1:-1;;;;;41186:44:0;;;;1136:18:1;;41186:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95549:3:::1;95530:15;:22;;;;95522:51;;;::::0;-1:-1:-1;;;95522:51:0;;12826:2:1;95522:51:0::1;::::0;::::1;12808:21:1::0;12865:2;12845:18;;;12838:30;-1:-1:-1;;;12884:18:1;;;12877:46;12940:18;;95522:51:0::1;12624:340:1::0;95522:51:0::1;95597:6;::::0;95584:37:::1;::::0;-1:-1:-1;;;95597:6:0;::::1;-1:-1:-1::0;;;;;95597:6:0::1;95605:15:::0;95584:12:::1;:37::i;:::-;95632:14;:32:::0;;::::1;::::0;;::::1;-1:-1:-1::0;;;95632:32:0::1;-1:-1:-1::0;;;;95632:32:0;;::::1;::::0;;;::::1;::::0;;95411:261::o;99489:194::-;40679:47;;-1:-1:-1;;;40679:47:0;;40715:10;40679:47;;;1163:51:1;40679:17:0;-1:-1:-1;;;;;40679:35:0;;;;1136:18:1;;40679:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59834:6:::1;99602:16;:27;;99594:36;;;::::0;::::1;;99641:15;:34:::0;99489:194::o;61722:152::-;40679:47;;-1:-1:-1;;;40679:47:0;;40715:10;40679:47;;;1163:51:1;40679:17:0;-1:-1:-1;;;;;40679:35:0;;;;1136:18:1;;40679:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61828:38:::1;61847:18;61828;:38::i;96136:671::-:0;40679:47;;-1:-1:-1;;;40679:47:0;;40715:10;40679:47;;;1163:51:1;40679:17:0;-1:-1:-1;;;;;40679:35:0;;;;1136:18:1;;40679:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;96296:36:0;;::::1;;::::0;::::1;::::0;-1:-1:-1;96296:97:0::1;;-1:-1:-1::0;;;;;;96353:40:0;;::::1;;;96296:97;96274:156;;;::::0;-1:-1:-1;;;96274:156:0;;8325:2:1;96274:156:0::1;::::0;::::1;8307:21:1::0;8364:1;8344:18;;;8337:29;-1:-1:-1;;;8382:18:1;;;8375:39;8431:18;;96274:156:0::1;8123:332:1::0;96274:156:0::1;96468:19;-1:-1:-1::0;;;;;96449:38:0::1;:15;-1:-1:-1::0;;;;;96449:38:0::1;;;96441:62;;;::::0;-1:-1:-1;;;96441:62:0;;13171:2:1;96441:62:0::1;::::0;::::1;13153:21:1::0;13210:2;13190:18;;;13183:30;-1:-1:-1;;;13229:18:1;;;13222:41;13280:18;;96441:62:0::1;12969:335:1::0;96441:62:0::1;96522:17;:32:::0;-1:-1:-1;;;;;96522:55:0;;::::1;:32:::0;::::1;:55;;96514:86;;;::::0;-1:-1:-1;;;96514:86:0;;13511:2:1;96514:86:0::1;::::0;::::1;13493:21:1::0;13550:2;13530:18;;;13523:30;-1:-1:-1;;;13569:18:1;;;13562:48;13627:18;;96514:86:0::1;13309:342:1::0;96514:86:0::1;-1:-1:-1::0;;;;;;;;;;;;;;96653:53:0;;::::1;::::0;;;96717:45;;;::::1;-1:-1:-1::0;;;;96717:45:0;;;-1:-1:-1;;;96773:26:0;;::::1;;:11;:26:::0;96136:671::o;56106:115::-;40502:11;:9;:11::i;:::-;56186:27:::1;56205:7;56186:18;:27::i;77465:417::-:0;77581:62;;;-1:-1:-1;;;;;13848:32:1;;77581:62:0;;;13830:51:1;13897:18;;;;13890:34;;;77581:62:0;;;;;;;;;;13803:18:1;;;;77581:62:0;;;;;;;;-1:-1:-1;;;;;77581:62:0;-1:-1:-1;;;77581:62:0;;;77661:44;77685:5;77581:62;77661:23;:44::i;:::-;77656:219;;77749:58;;-1:-1:-1;;;;;14133:32:1;;77749:58:0;;;14115:51:1;77805:1:0;14182:18:1;;;14175:45;77722:86:0;;77742:5;;-1:-1:-1;;;77772:22:0;14088:18:1;;77749:58:0;;;;-1:-1:-1;;77749:58:0;;;;;;;;;;;;;;-1:-1:-1;;;;;77749:58:0;-1:-1:-1;;;;;;77749:58:0;;;;;;;;;;77722:19;:86::i;:::-;77823:40;77843:5;77850:12;77823:19;:40::i;65698:326::-;-1:-1:-1;;;;;65993:19:0;;:23;;;65698:326::o;68453:229::-;68590:12;68622:52;68644:6;68652:4;68658:1;68661:12;68622:21;:52::i;:::-;68615:59;68453:229;-1:-1:-1;;;;68453:229:0:o;74571:177::-;74681:58;;-1:-1:-1;;;;;13848:32:1;;74681:58:0;;;13830:51:1;13897:18;;;13890:34;;;74654:86:0;;74674:5;;-1:-1:-1;;;74704:23:0;13803:18:1;;74681:58:0;13656:274:1;74654:86:0;74571:177;;;:::o;94011:116::-;94091:2;;94085:34;;-1:-1:-1;;;94085:34:0;;94113:4;94085:34;;;1163:51:1;94058:7:0;;-1:-1:-1;;;;;94091:2:0;;94085:19;;1136:18:1;;94085:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;94135:110::-;94180:4;94218:6;;;;;;;;;-1:-1:-1;;;;;94218:6:0;-1:-1:-1;;;;;94204:31:0;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;41346:99::-;41400:10;41422:4;41400:27;41392:45;;;;-1:-1:-1;;;41392:45:0;;14683:2:1;41392:45:0;;;14665:21:1;14722:1;14702:18;;;14695:29;-1:-1:-1;;;14740:18:1;;;14733:35;14785:18;;41392:45:0;14481:328:1;41392:45:0;41346:99::o;89741:365::-;89877:19;89899:17;-1:-1:-1;;;;;89899:29:0;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;89877:53;;89941:17;89975;:15;:17::i;:::-;89961:31;;:11;:31;:::i;:::-;89941:51;;90003:20;90055:9;90044:7;90027:14;:12;:14::i;:::-;:24;;;;:::i;:::-;90026:38;;;;:::i;:::-;90003:61;;90075:23;90085:12;90075:9;:23::i;:::-;;89796:310;;;89741:365;:::o;91334:734::-;91417:20;91460:12;:10;:12::i;:::-;91459:13;:48;;;;;91477:17;-1:-1:-1;;;;;91477:28:0;;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91476:31;91459:48;91455:338;;;91524:20;91547:17;:15;:17::i;:::-;91579:45;;;;;;;;;91613:11;91579:45;-1:-1:-1;;;;;91579:45:0;;;;;;-1:-1:-1;;;91579:45:0;;;;;;;;91524:40;;-1:-1:-1;91579:45:0;91643:46;;91639:143;;;91710:56;91718:47;91723:12;91737;:27;;;-1:-1:-1;;;;;91718:47:0;:4;:47::i;:::-;91710:7;:56::i;:::-;91509:284;;91455:338;59834:6;91907:17;;59834:6;91897:27;;;;:::i;:::-;91867:26;91878:14;:12;:14::i;:::-;91867:10;:26::i;:::-;:58;;;;:::i;:::-;91866:83;;;;:::i;:::-;91833:17;:15;:17::i;:::-;:116;;;;:::i;63301:914::-;63388:13;;;;63383:88;;-1:-1:-1;63418:13:0;:20;;-1:-1:-1;;63418:20:0;63434:4;63418:20;;;63301:914::o;63383:88::-;63549:26;63578:17;-1:-1:-1;;;;;63578:29:0;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;63549:60;;63644:18;63626:15;:36;63622:586;;;63799:17;;59834:6;;63770:47;;63799:17;;;;;63770:18;:47;:::i;:::-;63769:84;;;;:::i;:::-;63707:36;63725:18;63707:15;:36;:::i;:::-;63706:147;;63679:222;;;;-1:-1:-1;;;63679:222:0;;15541:2:1;63679:222:0;;;15523:21:1;15580:2;15560:18;;;15553:30;-1:-1:-1;;;15599:18:1;;;15592:41;15650:18;;63679:222:0;15339:335:1;63622:586:0;63944:15;63923:18;:36;63919:289;;;64095:15;;59834:6;;64066:45;;64095:15;;;;;64066:18;:45;:::i;:::-;64065:82;;;;:::i;:::-;64003:36;64024:15;64003:18;:36;:::i;92786:582::-;92871:63;;;;;;;;92917:17;92871:63;-1:-1:-1;;;;;92871:63:0;;;;;-1:-1:-1;;;92871:63:0;;;;;;;;-1:-1:-1;;;92871:63:0;;;;;;;;;;;-1:-1:-1;;;92871:63:0;;;;;;;;;92842:16;;92964:12;:10;:12::i;:::-;92963:13;:131;;;;;93057:18;:37;;;92993:101;;93011:18;:30;;;92993:48;;:15;:48;;;;:::i;:::-;:101;92963:131;:201;;;;-1:-1:-1;93131:33:0;;-1:-1:-1;;;;;93111:53:0;:17;:15;:17::i;:::-;:53;92963:201;:248;;;;-1:-1:-1;93181:11:0;:26;-1:-1:-1;;;93181:26:0;;-1:-1:-1;;;;;93181:26:0;:30;;92963:248;:296;;;;;93229:17;-1:-1:-1;;;;;93229:28:0;;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93228:31;92963:296;92945:416;;;93316:18;:33;;;93300:49;;:13;:49;93286:63;;92945:416;92860:508;92786:582;:::o;93888:115::-;93965:30;;-1:-1:-1;;;93965:30:0;;93989:4;93965:30;;;1163:51:1;93938:7:0;;93965:5;-1:-1:-1;;;;;93965:15:0;;;;1136:18:1;;93965:30:0;1017:203:1;61264:269:0;61375:1;61352:20;:24;61344:49;;;;-1:-1:-1;;;61344:49:0;;15881:2:1;61344:49:0;;;15863:21:1;15920:2;15900:18;;;15893:30;-1:-1:-1;;;15939:18:1;;;15932:42;15991:18;;61344:49:0;15679:336:1;61344:49:0;61436:16;61412:40;;;61404:62;;;;-1:-1:-1;;;61404:62:0;;16222:2:1;61404:62:0;;;16204:21:1;16261:1;16241:18;;;16234:29;-1:-1:-1;;;16279:18:1;;;16272:39;16328:18;;61404:62:0;16020:332:1;61404:62:0;61477:17;:48;;;;;;;;-1:-1:-1;;61477:48:0;;;;;;;;;61264:269::o;92657:121::-;92710:60;92718:51;92723:17;:15;:17::i;:::-;92742:11;:26;-1:-1:-1;;;92742:26:0;;-1:-1:-1;;;;;92742:26:0;92718:4;:51::i;90114:1212::-;90175:7;90199:14;90217:1;90199:19;90195:33;;-1:-1:-1;90227:1:0;;90114:1212;-1:-1:-1;90114:1212:0:o;90195:33::-;90264:12;:10;:12::i;:::-;90260:749;;;90444:2;;90353:161;;-1:-1:-1;;;90353:161:0;;85351:42;;90353:40;;:161;;90420:4;;-1:-1:-1;;;;;90444:2:0;;;;90465:14;;90444:2;;90353:161;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;90336:178;;90260:749;;;90547:41;;:::i;:::-;90851:6;;;90756:193;;-1:-1:-1;;;90756:193:0;;85351:42;;90756:44;;:193;;90827:4;;-1:-1:-1;;;90851:6:0;;;-1:-1:-1;;;;;90851:6:0;;90876:14;;90929:5;;90756:193;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;90735:214:0;-1:-1:-1;90986:1:0;90968:19;;;90964:33;;-1:-1:-1;90996:1:0;;90114:1212;-1:-1:-1;;90114:1212:0:o;90964:33::-;90532:477;90260:749;91147:171;;-1:-1:-1;;;91147:171:0;;91188:4;91147:171;;;12381:34:1;12431:18;;;12424:34;;;-1:-1:-1;;;;;91253:5:0;12494:15:1;;12474:18;;;12467:43;-1:-1:-1;12526:18:1;;;12519:34;;;12569:19;;;12562:51;91151:2:0;91147:14;;;;12315:19:1;;91147:171:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91127:191;90114:1212;-1:-1:-1;;90114:1212:0:o;94253:432::-;94488:62;;-1:-1:-1;;;94488:62:0;;-1:-1:-1;;;;;21474:32:1;;;94488:62:0;;;21456:51:1;94488:62:0;21543:23:1;;21523:18;;;21516:51;94381:32:0;;;;94502:6;94488:36;;;;21429:18:1;;94488:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;94366:184;;;;;94565:27;:58;;;;94597:26;94596:27;94565:58;94561:117;;;94640:26;;-1:-1:-1;;;94640:26:0;;22319:2:1;94640:26:0;;;22301:21:1;22358:2;22338:18;;;22331:30;-1:-1:-1;;;22377:18:1;;;22370:46;22433:18;;94640:26:0;22117:340:1;62066:191:0;59834:6;62150:18;:28;62142:52;;;;-1:-1:-1;;;62142:52:0;;22664:2:1;62142:52:0;;;22646:21:1;22703:2;22683:18;;;22676:30;-1:-1:-1;;;22722:18:1;;;22715:41;22773:18;;62142:52:0;22462:335:1;62142:52:0;62205:15;:44;;;;;;;;-1:-1:-1;;62205:44:0;;;;;;;;;62066:191::o;101925:522::-;101999:22;102024:14;:12;:14::i;:::-;101999:39;;102063:14;102053:7;:24;102049:81;;;102104:14;102094:24;;102049:81;102140:30;102173:19;102184:7;102173:10;:19::i;:::-;102140:52;;102203:18;102224;102234:7;102224:9;:18::i;:::-;102203:39;;59834:6;102343:15;;59834:6;102333:25;;;;:::i;:::-;102307:52;;:22;:52;:::i;:::-;102306:85;;;;:::i;:::-;102275:10;:116;;102253:186;;;;-1:-1:-1;;;102253:186:0;;9273:2:1;102253:186:0;;;9255:21:1;9312:2;9292:18;;;9285:30;-1:-1:-1;;;9331:18:1;;;9324:50;9391:18;;102253:186:0;9071:344:1;80077:602:0;80160:4;80467:12;80481:23;80516:5;-1:-1:-1;;;;;80508:19:0;80528:4;80508:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80466:67;;;;80564:7;:69;;;;-1:-1:-1;80576:17:0;;:22;;:56;;;80613:10;80602:30;;;;;;;;;;;;:::i;:::-;80564:107;;;;-1:-1:-1;;;;;;65993:19:0;;;:23;;80637:34;80544:127;80077:602;-1:-1:-1;;;;;80077:602:0:o;78917:649::-;79341:23;79367:69;79395:4;79367:69;;;;;;;;;;;;;;;;;79375:5;-1:-1:-1;;;;;79367:27:0;;;:69;;;;;:::i;:::-;79341:95;;79455:10;:17;79476:1;79455:22;:56;;;;79492:10;79481:30;;;;;;;;;;;;:::i;:::-;79447:111;;;;-1:-1:-1;;;79447:111:0;;23296:2:1;79447:111:0;;;23278:21:1;23335:2;23315:18;;;23308:30;23374:34;23354:18;;;23347:62;-1:-1:-1;;;23425:18:1;;;23418:40;23475:19;;79447:111:0;23094:406:1;69539:455:0;69709:12;69767:5;69742:21;:30;;69734:81;;;;-1:-1:-1;;;69734:81:0;;23707:2:1;69734:81:0;;;23689:21:1;23746:2;23726:18;;;23719:30;23785:34;23765:18;;;23758:62;-1:-1:-1;;;23836:18:1;;;23829:36;23882:19;;69734:81:0;23505:402:1;69734:81:0;69827:12;69841:23;69868:6;-1:-1:-1;;;;;69868:11:0;69887:5;69894:4;69868:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69826:73;;;;69917:69;69944:6;69952:7;69961:10;69973:12;69917:26;:69::i;:::-;69910:76;69539:455;-1:-1:-1;;;;;;;69539:455:0:o;94693:107::-;94752:7;94783:1;94779;:5;:13;;94791:1;94779:13;;;-1:-1:-1;94787:1:0;;94772:20;-1:-1:-1;94693:107:0:o;88952:781::-;89030:58;;-1:-1:-1;;;89030:58:0;;-1:-1:-1;;;;;89034:2:0;89030:15;;;;:58;;89054:4;;89069:5;;89077:7;;89086:1;;89030:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;89109:34:0;;-1:-1:-1;;;89109:34:0;;89137:4;89109:34;;;1163:51:1;89115:2:0;-1:-1:-1;;;;;89109:19:0;;;;1136:18:1;;89109:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;89099:44;;89177:41;;:::i;:::-;89272:16;59834:6;89322:15;;59834:6;89312:25;;;;:::i;:::-;89292:16;89300:7;89292;:16::i;:::-;:46;;;;:::i;:::-;89291:71;;;;:::i;:::-;89496:6;;89409:196;;-1:-1:-1;;;89409:196:0;;89272:90;;-1:-1:-1;85351:42:0;;89409:44;;:196;;89476:4;;-1:-1:-1;;;89496:6:0;;-1:-1:-1;;;;;89496:6:0;;89517:7;;89272:90;;89562:12;;89589:5;;89409:196;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;89670:17:0;:55;;-1:-1:-1;;;;;89670:55:0;-1:-1:-1;;;89709:15:0;89670:55;;;;;;-1:-1:-1;;;88952:781:0:o;92499:150::-;92559:7;92590:2;-1:-1:-1;;;;;92586:21:0;;92616:5;92624:16;92632:7;92624;:16::i;:::-;92586:55;;-1:-1:-1;;;;;;92586:55:0;;;;;;;-1:-1:-1;;;;;13848:32:1;;;92586:55:0;;;13830:51:1;13897:18;;;13890:34;13803:18;;92586:55:0;;;;;;;;;;;;;;;;;;;;;;72112:644;72297:12;72326:7;72322:427;;;72354:10;:17;72375:1;72354:22;72350:290;;-1:-1:-1;;;;;65993:19:0;;;72564:60;;;;-1:-1:-1;;;72564:60:0;;25145:2:1;72564:60:0;;;25127:21:1;25184:2;25164:18;;;25157:30;25223:31;25203:18;;;25196:59;25272:18;;72564:60:0;24943:353:1;72564:60:0;-1:-1:-1;72661:10:0;72654:17;;72322:427;72704:33;72712:10;72724:12;72704:7;:33::i;92076:195::-;92133:7;92240:6;;92204:59;;-1:-1:-1;;;92204:59:0;;-1:-1:-1;;;92240:6:0;;-1:-1:-1;;;;;92240:6:0;;;92204:59;;;21456:51:1;-1:-1:-1;;;92248:14:0;;;;;21523:18:1;;;21516:51;92218:6:0;92204:35;;;;;;21429:18:1;;92204:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92174:13;86766:4;92174:7;:13;:::i;:::-;92173:90;;;;:::i;92279:212::-;92336:7;92440:6;;92404:59;;-1:-1:-1;;;92404:59:0;;-1:-1:-1;;;92440:6:0;;-1:-1:-1;;;;;92440:6:0;;;92404:59;;;21456:51:1;-1:-1:-1;;;92448:14:0;;;;;21523:18:1;;;21516:51;86766:4:0;;92418:6;92404:35;;;;21429:18:1;;92404:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92377:86;;:7;:86;:::i;73298:552::-;73459:17;;:21;73455:388;;73691:10;73685:17;73748:15;73735:10;73731:2;73727:19;73720:44;73455:388;73818:12;73811:20;;-1:-1:-1;;;73811:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:131:1:-;-1:-1:-1;;;;;89:31:1;;79:42;;69:70;;135:1;132;125:12;150:247;209:6;262:2;250:9;241:7;237:23;233:32;230:52;;;278:1;275;268:12;230:52;317:9;304:23;336:31;361:5;336:31;:::i;1885:188::-;1953:20;;-1:-1:-1;;;;;2002:46:1;;1992:57;;1982:85;;2063:1;2060;2053:12;2078:528;2153:6;2161;2169;2222:2;2210:9;2201:7;2197:23;2193:32;2190:52;;;2238:1;2235;2228:12;2190:52;2261:29;2280:9;2261:29;:::i;:::-;2251:39;;2340:2;2329:9;2325:18;2312:32;2384:14;2377:5;2373:26;2366:5;2363:37;2353:65;;2414:1;2411;2404:12;2353:65;2437:5;-1:-1:-1;2494:2:1;2479:18;;2466:32;2542:12;2529:26;;2517:39;;2507:67;;2570:1;2567;2560:12;2507:67;2593:7;2583:17;;;2078:528;;;;;:::o;2611:180::-;2670:6;2723:2;2711:9;2702:7;2698:23;2694:32;2691:52;;;2739:1;2736;2729:12;2691:52;-1:-1:-1;2762:23:1;;2611:180;-1:-1:-1;2611:180:1:o;2796:385::-;2882:6;2890;2898;2906;2959:3;2947:9;2938:7;2934:23;2930:33;2927:53;;;2976:1;2973;2966:12;2927:53;-1:-1:-1;;2999:23:1;;;3069:2;3054:18;;3041:32;;-1:-1:-1;3120:2:1;3105:18;;3092:32;;3171:2;3156:18;3143:32;;-1:-1:-1;2796:385:1;-1:-1:-1;2796:385:1:o;3186:118::-;3272:5;3265:13;3258:21;3251:5;3248:32;3238:60;;3294:1;3291;3284:12;3309:382;3374:6;3382;3435:2;3423:9;3414:7;3410:23;3406:32;3403:52;;;3451:1;3448;3441:12;3403:52;3490:9;3477:23;3509:31;3534:5;3509:31;:::i;:::-;3559:5;-1:-1:-1;3616:2:1;3601:18;;3588:32;3629:30;3588:32;3629:30;:::i;:::-;3678:7;3668:17;;;3309:382;;;;;:::o;3696:250::-;3781:1;3791:113;3805:6;3802:1;3799:13;3791:113;;;3881:11;;;3875:18;3862:11;;;3855:39;3827:2;3820:10;3791:113;;;-1:-1:-1;;3938:1:1;3920:16;;3913:27;3696:250::o;3951:270::-;3992:3;4030:5;4024:12;4057:6;4052:3;4045:19;4073:76;4142:6;4135:4;4130:3;4126:14;4119:4;4112:5;4108:16;4073:76;:::i;:::-;4203:2;4182:15;-1:-1:-1;;4178:29:1;4169:39;;;;4210:4;4165:50;;3951:270;-1:-1:-1;;3951:270:1:o;4226:298::-;4409:6;4402:14;4395:22;4384:9;4377:41;4454:2;4449;4438:9;4434:18;4427:30;4358:4;4474:44;4514:2;4503:9;4499:18;4491:6;4474:44;:::i;4529:241::-;4585:6;4638:2;4626:9;4617:7;4613:23;4609:32;4606:52;;;4654:1;4651;4644:12;4606:52;4693:9;4680:23;4712:28;4734:5;4712:28;:::i;4775:248::-;4843:6;4851;4904:2;4892:9;4883:7;4879:23;4875:32;4872:52;;;4920:1;4917;4910:12;4872:52;-1:-1:-1;;4943:23:1;;;5013:2;4998:18;;;4985:32;;-1:-1:-1;4775:248:1:o;5529:315::-;5597:6;5605;5658:2;5646:9;5637:7;5633:23;5629:32;5626:52;;;5674:1;5671;5664:12;5626:52;5713:9;5700:23;5732:31;5757:5;5732:31;:::i;:::-;5782:5;5834:2;5819:18;;;;5806:32;;-1:-1:-1;;;5529:315:1:o;5849:276::-;5907:6;5960:2;5948:9;5939:7;5935:23;5931:32;5928:52;;;5976:1;5973;5966:12;5928:52;6015:9;6002:23;6065:10;6058:5;6054:22;6047:5;6044:33;6034:61;;6091:1;6088;6081:12;6327:260;6395:6;6403;6456:2;6444:9;6435:7;6431:23;6427:32;6424:52;;;6472:1;6469;6462:12;6424:52;6495:29;6514:9;6495:29;:::i;:::-;6485:39;;6543:38;6577:2;6566:9;6562:18;6543:38;:::i;:::-;6533:48;;6327:260;;;;;:::o;7589:184::-;7659:6;7712:2;7700:9;7691:7;7687:23;7683:32;7680:52;;;7728:1;7725;7718:12;7680:52;-1:-1:-1;7751:16:1;;7589:184;-1:-1:-1;7589:184:1:o;8806:127::-;8867:10;8862:3;8858:20;8855:1;8848:31;8898:4;8895:1;8888:15;8922:4;8919:1;8912:15;8938:128;9005:9;;;9026:11;;;9023:37;;;9040:18;;:::i;10435:455::-;-1:-1:-1;;;;;10730:15:1;;;10712:34;;10782:15;;;;10777:2;10762:18;;10755:43;10829:2;10814:18;;10807:34;10872:2;10857:18;;10850:34;;;;10661:3;10646:19;;10435:455::o;11230:519::-;11318:6;11326;11334;11387:2;11375:9;11366:7;11362:23;11358:32;11355:52;;;11403:1;11400;11393:12;11355:52;11435:9;11429:16;11454:31;11479:5;11454:31;:::i;:::-;11554:2;11539:18;;11533:25;11504:5;;-1:-1:-1;11567:33:1;11533:25;11567:33;:::i;:::-;11671:2;11656:18;;11650:25;11619:7;;-1:-1:-1;11684:33:1;11650:25;11684:33;:::i;14231:245::-;14298:6;14351:2;14339:9;14330:7;14326:23;14322:32;14319:52;;;14367:1;14364;14357:12;14319:52;14399:9;14393:16;14418:28;14440:5;14418:28;:::i;14814:168::-;14887:9;;;14918;;14935:15;;;14929:22;;14915:37;14905:71;;14956:18;;:::i;14987:217::-;15027:1;15053;15043:132;;15097:10;15092:3;15088:20;15085:1;15078:31;15132:4;15129:1;15122:15;15160:4;15157:1;15150:15;15043:132;-1:-1:-1;15189:9:1;;14987:217::o;15209:125::-;15274:9;;;15295:10;;;15292:36;;;15308:18;;:::i;16357:237::-;16438:1;16431:5;16428:12;16418:143;;16483:10;16478:3;16474:20;16471:1;16464:31;16518:4;16515:1;16508:15;16546:4;16543:1;16536:15;16418:143;16570:18;;16357:237::o;16599:2529::-;16667:3;16705:5;16699:12;16732:6;16727:3;16720:19;16758:4;16799:2;16794:3;16790:12;16824:11;16851;16844:18;;16901:6;16898:1;16894:14;16887:5;16883:26;16871:38;;16943:2;16936:5;16932:14;16964:1;16974:2128;16988:6;16985:1;16982:13;16974:2128;;;17059:5;17053:4;17049:16;17044:3;17037:29;17095:6;17089:13;17125:4;17168:2;17162:9;17197:2;17191:4;17184:16;17241:12;17235:19;17230:2;17224:4;17220:13;17213:42;17302:2;17288:12;17284:21;17278:28;17329:3;17367:2;17362;17356:4;17352:13;17345:25;17393:4;17383:14;;17444:2;17430:12;17426:21;17420:28;17471:3;17509:2;17504;17498:4;17494:13;17487:25;17571:2;17557:12;17553:21;17547:28;17525:50;;17598:3;17588:13;;17614:56;17666:2;17660:4;17656:13;17640:14;17614:56;:::i;:::-;17711:21;;;17705:28;;-1:-1:-1;17757:3:1;;17773:50;17808:14;;;17705:28;-1:-1:-1;;;;;974:31:1;962:44;;908:104;17773:50;17864:21;;17858:28;;-1:-1:-1;17910:3:1;17926:50;17961:14;;;17858:28;-1:-1:-1;;;;;974:31:1;962:44;;908:104;17926:50;18017:21;;;18011:28;;-1:-1:-1;18063:3:1;;18079:50;18114:14;;;18011:28;-1:-1:-1;;;;;974:31:1;962:44;;908:104;18079:50;18170:22;;;18164:29;;-1:-1:-1;18217:3:1;;18233:50;18268:14;;;18164:29;-1:-1:-1;;;;;974:31:1;962:44;;908:104;18233:50;18313:22;;18307:29;18360:3;18383:14;;;18376:27;;;;18433:22;;;18427:29;18480:6;18506:14;;;18499:27;;;;18568:22;;;18562:29;18556:3;18546:14;;18539:53;18633:22;;18627:29;18686:3;18676:14;;18669:27;;;;18627:29;-1:-1:-1;18722:48:1;18765:3;18755:14;;18627:29;18722:48;:::i;:::-;18709:61;;18819:2;18815;18811:11;18805:18;18783:40;;18869:4;18862:5;18858:16;18853:2;18847:4;18843:13;18836:39;18902;18935:5;18919:14;18902:39;:::i;:::-;18982:11;;;18976:18;18961:13;;18954:41;;;;-1:-1:-1;19080:12:1;;;;18888:53;-1:-1:-1;19045:15:1;;;;17010:1;17003:9;16974:2128;;;-1:-1:-1;19118:4:1;;16599:2529;-1:-1:-1;;;;;;;16599:2529:1:o;19133:719::-;19255:1;19251;19246:3;19242:11;19238:19;19230:5;19224:12;19220:38;19215:3;19208:51;19308:4;19301:5;19297:16;19291:23;19284:4;19279:3;19275:14;19268:47;19190:3;19361:4;19354:5;19350:16;19344:23;19399:4;19392;19387:3;19383:14;19376:28;19425:73;19492:4;19487:3;19483:14;19469:12;19425:73;:::i;:::-;19413:85;;19546:4;19539:5;19535:16;19529:23;19594:3;19588:4;19584:14;19577:4;19572:3;19568:14;19561:38;19622:65;19682:4;19666:14;19622:65;:::i;:::-;19608:79;;;19735:4;19728:5;19724:16;19718:23;19785:3;19777:6;19773:16;19766:4;19761:3;19757:14;19750:40;19806;19839:6;19823:14;19806:40;:::i;19857:630::-;-1:-1:-1;;;;;20208:15:1;;;20190:34;;20260:15;;20255:2;20240:18;;20233:43;20307:2;20292:18;;20285:34;;;20350:2;20335:18;;20328:34;;;20170:3;20393;20378:19;;20371:32;;;20133:4;;20420:61;;20461:19;;20453:6;20420:61;:::i;20492:245::-;20571:6;20579;20632:2;20620:9;20611:7;20607:23;20603:32;20600:52;;;20648:1;20645;20638:12;20600:52;-1:-1:-1;;20671:16:1;;20727:2;20712:18;;;20706:25;20671:16;;20706:25;;-1:-1:-1;20492:245:1:o;21578:534::-;21659:6;21667;21675;21728:2;21716:9;21707:7;21703:23;21699:32;21696:52;;;21744:1;21741;21734:12;21696:52;21776:9;21770:16;21795:28;21817:5;21795:28;:::i;:::-;21892:2;21877:18;;21871:25;21842:5;;-1:-1:-1;21940:6:1;21927:20;;21915:33;;21905:61;;21962:1;21959;21952:12;21905:61;22037:2;22022:18;;22016:25;21985:7;;-1:-1:-1;22050:30:1;22016:25;22050:30;:::i;22802:287::-;22931:3;22969:6;22963:13;22985:66;23044:6;23039:3;23032:4;23024:6;23020:17;22985:66;:::i;:::-;23067:16;;;;;22802:287;-1:-1:-1;;22802:287:1:o;23912:1026::-;-1:-1:-1;;;;;24362:15:1;;;24344:34;;24414:15;;24409:2;24394:18;;24387:43;24461:2;24446:18;;24439:34;;;24504:2;24489:18;;24482:34;;;24553:13;;24547:3;24532:19;;24525:42;24333:1;24610:17;;24604:24;24324:3;24583:19;;24576:53;24684:4;24672:17;;24666:24;24660:3;24645:19;;24638:53;24746:4;24734:17;;24728:24;24722:3;24707:19;;24700:53;24808:4;24796:17;;24790:24;24784:3;24769:19;;24762:53;24294:3;24846;24831:19;;24824:31;;;24265:4;;24872:60;24913:18;;;24905:6;24872:60;:::i;:::-;24864:68;23912:1026;-1:-1:-1;;;;;;;;;23912:1026:1:o;25301:219::-;25450:2;25439:9;25432:21;25413:4;25470:44;25510:2;25499:9;25495:18;25487:6;25470:44;:::i
Swarm Source
ipfs://80aa6f66d3610913017e3c5a184bde24093d96e2dfe9bd5e62ab7b7ce4dbbc96
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 27 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.