Feature Tip: Add private address tag to any address under My Name Tag !
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 49 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Redeem | 24392750 | 3 days ago | IN | 0 ETH | 0.00043318 | ||||
| Approve | 24392701 | 3 days ago | IN | 0 ETH | 0.00017187 | ||||
| Redeem | 24392586 | 3 days ago | IN | 0 ETH | 0.00049941 | ||||
| Redeem | 24334266 | 11 days ago | IN | 0 ETH | 0.00004112 | ||||
| Redeem | 24291410 | 17 days ago | IN | 0 ETH | 0.00011338 | ||||
| Redeem | 24176184 | 33 days ago | IN | 0 ETH | 0.00012726 | ||||
| Deposit | 24098850 | 44 days ago | IN | 0 ETH | 0.00000497 | ||||
| Redeem | 23918860 | 69 days ago | IN | 0 ETH | 0.0000436 | ||||
| Redeem | 23824053 | 82 days ago | IN | 0 ETH | 0.00015773 | ||||
| Deposit | 23771412 | 90 days ago | IN | 0 ETH | 0.00002065 | ||||
| Redeem | 23765902 | 91 days ago | IN | 0 ETH | 0.00001073 | ||||
| Deposit | 23702578 | 99 days ago | IN | 0 ETH | 0.00001154 | ||||
| Deposit | 23662385 | 105 days ago | IN | 0 ETH | 0.000019 | ||||
| Redeem | 23567145 | 118 days ago | IN | 0 ETH | 0.00003011 | ||||
| Deposit | 23537448 | 122 days ago | IN | 0 ETH | 0.0000232 | ||||
| Redeem | 23519522 | 125 days ago | IN | 0 ETH | 0.00044041 | ||||
| Deposit | 23494820 | 128 days ago | IN | 0 ETH | 0.00018012 | ||||
| Redeem | 23336857 | 151 days ago | IN | 0 ETH | 0.00015099 | ||||
| Deposit | 23317759 | 153 days ago | IN | 0 ETH | 0.00014041 | ||||
| Redeem | 23102814 | 183 days ago | IN | 0 ETH | 0.00017913 | ||||
| Deposit | 23046712 | 191 days ago | IN | 0 ETH | 0.00040361 | ||||
| Redeem | 22942855 | 206 days ago | IN | 0 ETH | 0.00077381 | ||||
| Deposit | 22933272 | 207 days ago | IN | 0 ETH | 0.00113532 | ||||
| Redeem | 22924389 | 208 days ago | IN | 0 ETH | 0.00015131 | ||||
| Redeem | 22840209 | 220 days ago | IN | 0 ETH | 0.00019238 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
SkyCompounder
Compiler Version
v0.8.18+commit.87f61d96
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-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);
function maxWithdraw(
address owner,
uint256 /*maxLoss*/
) external view returns (uint256);
function maxRedeem(
address owner,
uint256 /*maxLoss*/
) external view 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 setName(string calldata _newName) 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 =
0x254A93feff3BEeF9cA004E913bB5443754e8aB19;
/*//////////////////////////////////////////////////////////////
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 IStaking {
function stakingToken() external view returns (address);
function rewardsToken() external view returns (address);
function paused() external view returns (bool);
function earned(address) external view returns (uint256);
function stake(uint256 _amount, uint16 _referral) external;
function withdraw(uint256 _amount) external;
function getReward() external;
}
interface IReferral{
function deposit(uint256, address, uint16) external;
}
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external returns (uint256 amountA, uint256 amountB, uint256 liquidity);
function addLiquidityETH(
address token,
uint256 amountTokenDesired,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
)
external
payable
returns (uint256 amountToken, uint256 amountETH, uint256 liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external returns (uint256 amountA, uint256 amountB);
function removeLiquidityETH(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) external returns (uint256 amountToken, uint256 amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountA, uint256 amountB);
function removeLiquidityETHWithPermit(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountToken, uint256 amountETH);
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapTokensForExactTokens(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactETHForTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function swapTokensForExactETH(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactTokensForETH(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapETHForExactTokens(
uint256 amountOut,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function quote(
uint256 amountA,
uint256 reserveA,
uint256 reserveB
) external pure returns (uint256 amountB);
function getAmountOut(
uint256 amountIn,
uint256 reserveIn,
uint256 reserveOut
) external pure returns (uint256 amountOut);
function getAmountIn(
uint256 amountOut,
uint256 reserveIn,
uint256 reserveOut
) external pure returns (uint256 amountIn);
function getAmountsOut(
uint256 amountIn,
address[] calldata path
) external view returns (uint256[] memory amounts);
function getAmountsIn(
uint256 amountOut,
address[] calldata path
) external view returns (uint256[] memory amounts);
}
interface IUniswapV2Router02 is IUniswapV2Router01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) external returns (uint256 amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
}
/// @title Callback for IUniswapV3PoolActions#swap
/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface
interface IUniswapV3SwapCallback {
/// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.
/// @dev In the implementation you must pay the pool tokens owed for the swap.
/// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.
/// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.
/// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by
/// the end of the swap. If positive, the callback must send that amount of token0 to the pool.
/// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by
/// the end of the swap. If positive, the callback must send that amount of token1 to the pool.
/// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call
function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata data
) external;
}
/// @title Router token swapping functionality
/// @notice Functions for swapping tokens via Uniswap V3
interface ISwapRouter is IUniswapV3SwapCallback {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another token
/// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata
/// @return amountOut The amount of the received token
function exactInputSingle(
ExactInputSingleParams calldata params
) external payable returns (uint256 amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata
/// @return amountOut The amount of the received token
function exactInput(
ExactInputParams calldata params
) external payable returns (uint256 amountOut);
struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
uint160 sqrtPriceLimitX96;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another token
/// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata
/// @return amountIn The amount of the input token
function exactOutputSingle(
ExactOutputSingleParams calldata params
) external payable returns (uint256 amountIn);
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata
/// @return amountIn The amount of the input token
function exactOutput(
ExactOutputParams calldata params
) external payable returns (uint256 amountIn);
// Taken from https://soliditydeveloper.com/uniswap3
// Manually added to the interface
function refundETH() external payable;
}
/**
* @title UniswapV3Swapper
* @author Yearn.finance
* @dev This is a simple contract that can be inherited by any tokenized
* strategy that would like to use Uniswap V3 for swaps. It hold all needed
* logic to perform both exact input and exact output swaps.
*
* The global address variables default to the ETH mainnet addresses but
* remain settable by the inheriting contract to allow for customization
* based on needs or chain its used on.
*
* The only variables that are required to be set are the specific fees
* for each token pair. The inheriting contract can use the {_setUniFees}
* function to easily set this for any token pairs needed.
*/
contract UniswapV3Swapper {
using SafeERC20 for ERC20;
// Optional Variable to be set to not sell dust.
uint256 public minAmountToSell;
// Defaults to WETH on mainnet.
address public base = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
// Defaults to Uniswap V3 router on mainnet.
address public router = 0xE592427A0AEce92De3Edee1F18E0157C05861564;
// Fees for the Uni V3 pools. Each fee should get set each way in
// the mapping so no matter the direction the correct fee will get
// returned for any two tokens.
mapping(address => mapping(address => uint24)) public uniFees;
/**
* @dev All fess will default to 0 on creation. A strategist will need
* To set the mapping for the tokens expected to swap. This function
* is to help set the mapping. It can be called internally during
* initialization, through permissioned functions etc.
*/
function _setUniFees(
address _token0,
address _token1,
uint24 _fee
) internal virtual {
uniFees[_token0][_token1] = _fee;
uniFees[_token1][_token0] = _fee;
}
/**
* @dev Used to swap a specific amount of `_from` to `_to`.
* This will check and handle all allowances as well as not swapping
* unless `_amountIn` is greater than the set `_minAmountOut`
*
* If one of the tokens matches with the `base` token it will do only
* one jump, otherwise will do two jumps.
*
* The corresponding uniFees for each token pair will need to be set
* other wise this function will revert.
*
* @param _from The token we are swapping from.
* @param _to The token we are swapping to.
* @param _amountIn The amount of `_from` we will swap.
* @param _minAmountOut The min of `_to` to get out.
* @return _amountOut The actual amount of `_to` that was swapped to
*/
function _swapFrom(
address _from,
address _to,
uint256 _amountIn,
uint256 _minAmountOut
) internal virtual returns (uint256 _amountOut) {
if (_amountIn > minAmountToSell) {
_checkAllowance(router, _from, _amountIn);
if (_from == base || _to == base) {
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter
.ExactInputSingleParams(
_from, // tokenIn
_to, // tokenOut
uniFees[_from][_to], // from-to fee
address(this), // recipient
block.timestamp, // deadline
_amountIn, // amountIn
_minAmountOut, // amountOut
0 // sqrtPriceLimitX96
);
_amountOut = ISwapRouter(router).exactInputSingle(params);
} else {
bytes memory path = abi.encodePacked(
_from, // tokenIn
uniFees[_from][base], // from-base fee
base, // base token
uniFees[base][_to], // base-to fee
_to // tokenOut
);
_amountOut = ISwapRouter(router).exactInput(
ISwapRouter.ExactInputParams(
path,
address(this),
block.timestamp,
_amountIn,
_minAmountOut
)
);
}
}
}
/**
* @dev Used to swap a specific amount of `_to` from `_from` unless
* it takes more than `_maxAmountFrom`.
*
* This will check and handle all allowances as well as not swapping
* unless `_maxAmountFrom` is greater than the set `minAmountToSell`
*
* If one of the tokens matches with the `base` token it will do only
* one jump, otherwise will do two jumps.
*
* The corresponding uniFees for each token pair will need to be set
* other wise this function will revert.
*
* @param _from The token we are swapping from.
* @param _to The token we are swapping to.
* @param _amountTo The amount of `_to` we need out.
* @param _maxAmountFrom The max of `_from` we will swap.
* @return _amountIn The actual amount of `_from` swapped.
*/
function _swapTo(
address _from,
address _to,
uint256 _amountTo,
uint256 _maxAmountFrom
) internal virtual returns (uint256 _amountIn) {
if (_maxAmountFrom > minAmountToSell) {
_checkAllowance(router, _from, _maxAmountFrom);
if (_from == base || _to == base) {
ISwapRouter.ExactOutputSingleParams memory params = ISwapRouter
.ExactOutputSingleParams(
_from, // tokenIn
_to, // tokenOut
uniFees[_from][_to], // from-to fee
address(this), // recipient
block.timestamp, // deadline
_amountTo, // amountOut
_maxAmountFrom, // maxAmountIn
0 // sqrtPriceLimitX96
);
_amountIn = ISwapRouter(router).exactOutputSingle(params);
} else {
bytes memory path = abi.encodePacked(
_to,
uniFees[base][_to], // base-to fee
base,
uniFees[_from][base], // from-base fee
_from
);
_amountIn = ISwapRouter(router).exactOutput(
ISwapRouter.ExactOutputParams(
path,
address(this),
block.timestamp,
_amountTo, // How much we want out
_maxAmountFrom
)
);
}
}
}
/**
* @dev Internal safe function to make sure the contract you want to
* interact with has enough allowance to pull the desired tokens.
*
* @param _contract The address of the contract that will move the token.
* @param _token The ERC-20 token that will be getting spent.
* @param _amount The amount of `_token` to be spent.
*/
function _checkAllowance(
address _contract,
address _token,
uint256 _amount
) internal virtual {
if (ERC20(_token).allowance(address(this), _contract) < _amount) {
ERC20(_token).safeApprove(_contract, 0);
ERC20(_token).safeApprove(_contract, _amount);
}
}
}
/// @title yearn-v3-SkyCompounder
/// @author mil0x
/// @notice yearn v3 Strategy that autocompounds staking rewards.
contract SkyCompounder is BaseHealthCheck, UniswapV3Swapper {
using SafeERC20 for ERC20;
///@notice Represents if we should claim rewards. Default to true.
bool public claimRewards = true;
///@notice Represents if we should use UniswapV3 (true) or UniswapV2 (false) to sell rewards. The default is false = UniswapV2.
bool public useUniV3;
///@notice yearn's referral code
uint16 public referral = 1007;
///@notice yearn governance
address public constant GOV = 0xFEB4acf3df3cDEA7399794D0869ef76A6EfAff52;
address public immutable staking;
address public immutable rewardsToken;
address private constant uniV2router = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; // Uniswap V2 router on Mainnet
// choices for base
address private constant USDS = 0xdC035D45d973E3EC169d2276DDab16f1e407384F;
address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
address private constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
address private constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
uint256 private constant ASSET_DUST = 100;
constructor(address _staking, string memory _name) BaseHealthCheck(USDS, _name) {
require(IStaking(_staking).paused() == false, "paused");
require(USDS == IStaking(_staking).stakingToken(), "!stakingToken");
rewardsToken = IStaking(_staking).rewardsToken();
ERC20(USDS).forceApprove(_staking, type(uint256).max);
ERC20(rewardsToken).forceApprove(uniV2router, type(uint256).max);
staking = _staking;
base = USDS;
minAmountToSell = 50e18; // Set the min amount for the swapper to sell
}
function _deployFunds(uint256 _amount) internal override {
IStaking(staking).stake(_amount, referral);
}
function _freeFunds(uint256 _amount) internal override {
IStaking(staking).withdraw(_amount);
}
function _harvestAndReport() internal override returns (uint256 _totalAssets) {
if (claimRewards) {
IStaking(staking).getReward();
if (useUniV3) { // UniV3
_swapFrom(rewardsToken, address(asset), balanceOfRewards(), 0); // minAmountOut = 0 since we only sell rewards
} else { // UniV2
_uniV2swapFrom(rewardsToken, address(asset), balanceOfRewards(), 0); // minAmountOut = 0 since we only sell rewards
}
}
uint256 balance = balanceOfAsset();
if (TokenizedStrategy.isShutdown()) {
_totalAssets = balance + balanceOfStake();
} else {
if (balance > ASSET_DUST) {
_deployFunds(balance);
}
_totalAssets = balanceOfStake();
}
}
function availableDepositLimit(address /*_owner*/) public view override returns (uint256) {
bool paused = IStaking(staking).paused();
if (paused) return 0;
return type(uint256).max;
}
function _uniV2swapFrom(address _from, address _to, uint256 _amountIn, uint256 _minAmountOut) internal {
if (_amountIn > minAmountToSell) {
IUniswapV2Router02(uniV2router).swapExactTokensForTokens(_amountIn, _minAmountOut, _getTokenOutPath(_from, _to), address(this), block.timestamp);
}
}
function _getTokenOutPath(address _tokenIn, address _tokenOut) internal view virtual returns (address[] memory _path) {
address _base = base;
bool isBase = _tokenIn == _base || _tokenOut == _base;
_path = new address[](isBase ? 2 : 3);
_path[0] = _tokenIn;
if (isBase) {
_path[1] = _tokenOut;
} else {
_path[1] = _base;
_path[2] = _tokenOut;
}
}
function _min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function balanceOfAsset() public view returns (uint256) {
return asset.balanceOf(address(this));
}
function balanceOfStake() public view returns (uint256 _amount) {
return ERC20(staking).balanceOf(address(this));
}
function balanceOfRewards() public view returns (uint256) {
return ERC20(rewardsToken).balanceOf(address(this));
}
function claimableRewards() public view returns (uint256) {
return IStaking(staking).earned(address(this));
}
//////// EXTERNAL
/**
* @notice Set the `claimRewards` bool.
* @dev For management to set if the strategy should claim rewards during reports.
* Can be turned off due to rewards being turned off or cause of an issue
* in either the strategy or compound contracts.
*
* @param _claimRewards Bool representing if rewards should be claimed.
*/
function setClaimRewards(bool _claimRewards) external onlyManagement {
claimRewards = _claimRewards;
}
/**
* @notice Set fees for UniswapV3 to sell rewardsToken
* @param _rewardToBase fee reward to base (weth/asset)
* @param _baseToAsset fee base (weth/asset) to asset
*/
function setUseUniV3andFees(bool _useUniV3, uint24 _rewardToBase, uint24 _baseToAsset) external onlyManagement {
useUniV3 = _useUniV3;
_setUniFees(rewardsToken, base, _rewardToBase);
_setUniFees(base, address(asset), _baseToAsset);
}
/**
* @notice Set the minimum amount of rewardsToken to sell
* @param _minAmountToSell minimum amount to sell in wei
*/
function setMinAmountToSell(uint256 _minAmountToSell) external onlyManagement {
minAmountToSell = _minAmountToSell;
}
/**
* @notice Set the base token between USDS, DAI, USDC, or WETH. (Default = USDS)
* @param _base address of either USDS, DAI, USDC, or WETH.
* @dev This can be used for management to change which pool
* to trade reward tokens.
*/
function setBase(address _base) external onlyManagement {
if (_base == USDS) {
base = USDS;
} else if (_base == DAI) {
base = DAI;
} else if (_base == USDC) {
base = USDC;
} else if (_base == WETH) {
base = WETH;
} else {
revert("!base in list");
}
}
/**
* @notice Set the referral code for staking.
* @param _referral uint16 referral code
*/
function setReferral(uint16 _referral) external onlyManagement {
referral = _referral;
}
function _emergencyWithdraw(uint256 _amount) internal override {
_amount = _min(_amount, balanceOfStake());
_freeFunds(_amount);
}
/*//////////////////////////////////////////////////////////////
GOVERNANCE:
//////////////////////////////////////////////////////////////*/
/// @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");
ERC20(_token).safeTransfer(GOV, ERC20(_token).balanceOf(address(this)));
}
modifier onlyGovernance() {
require(msg.sender == GOV, "!gov");
_;
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
},
"remappings": []
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_staking","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":[{"internalType":"address","name":"","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":"balanceOfRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceOfStake","outputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"base","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimRewards","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimableRewards","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":"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":"lossLimitRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minAmountToSell","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"profitLimitRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referral","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_base","type":"address"}],"name":"setBase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_claimRewards","type":"bool"}],"name":"setClaimRewards","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":"uint256","name":"_minAmountToSell","type":"uint256"}],"name":"setMinAmountToSell","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newProfitLimitRatio","type":"uint256"}],"name":"setProfitLimitRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_referral","type":"uint16"}],"name":"setReferral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_useUniV3","type":"bool"},{"internalType":"uint24","name":"_rewardToBase","type":"uint24"},{"internalType":"uint24","name":"_baseToAsset","type":"uint24"}],"name":"setUseUniV3andFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"shutdownWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"staking","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"tokenizedStrategyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"uniFees","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"useUniV3","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]Contract Creation Code
6101006040526000805462ffffff1916622710011790556002805473c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b0319918216179091556003805473e592427a0aece92de3edee1f18e0157c0586156492169190911790556005805463ffff00ff19166303ef00011790553480156200008057600080fd5b5060405162002faa38038062002faa833981016040819052620000a391620008fa565b73dc035d45d973e3ec169d2276ddab16f1e407384f60808190523060a0526040518290829082906200011b90620000e79084908490339081908190602401620009f6565b60408051601f198184030181529190526020810180516001600160e01b03908116634b839d7360e11b17909152620003e616565b5073254a93feff3beef9ca004e913bb5443754e8ab197f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5550505050816001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000196573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001bc919062000a39565b15620001f85760405162461bcd60e51b81526020600482015260066024820152651c185d5cd95960d21b60448201526064015b60405180910390fd5b816001600160a01b03166372f702f36040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000237573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200025d919062000a5d565b6001600160a01b031673dc035d45d973e3ec169d2276ddab16f1e407384f6001600160a01b031614620002c35760405162461bcd60e51b815260206004820152600d60248201526c10b9ba30b5b4b733aa37b5b2b760991b6044820152606401620001ef565b816001600160a01b031663d1af0c7d6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000302573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000328919062000a5d565b6001600160a01b031660e0526200036373dc035d45d973e3ec169d2276ddab16f1e407384f836000196200047a602090811b62000f5717901c565b620003a0737a250d5630b4cf539739df2c5dacb4c659f2488d60001960e0516001600160a01b03166200047a60201b62000f57179092919060201c565b506001600160a01b031660c052600280546001600160a01b03191673dc035d45d973e3ec169d2276ddab16f1e407384f1790556802b5e3af16b188000060015562000aae565b606060008073254a93feff3beef9ca004e913bb5443754e8ab196001600160a01b03168460405162000419919062000a7b565b600060405180830381855af49150503d806000811462000456576040519150601f19603f3d011682016040523d82523d6000602084013e6200045b565b606091505b50915091508162000473576040513d806000833e8082fd5b9392505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152620004d490859083906200055016565b6200054a576040516001600160a01b0384166024820152600060448201526200053e90859063095ea7b360e01b9060640160408051808303601f190181529190526020810180516001600160e01b0319939093166001600160e01b03938416179052906200060816565b6200054a848262000608565b50505050565b6000806000846001600160a01b0316846040516200056f919062000a7b565b6000604051808303816000865af19150503d8060008114620005ae576040519150601f19603f3d011682016040523d82523d6000602084013e620005b3565b606091505b5091509150818015620005e1575080511580620005e1575080806020019051810190620005e1919062000a39565b8015620005ff5750620005ff85620006ee60201b6200101f1760201c565b95945050505050565b600062000664826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620006fd60201b6200102e179092919060201c565b90508051600014806200068857508080602001905181019062000688919062000a39565b620006e95760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401620001ef565b505050565b6001600160a01b03163b151590565b60606200070e848460008562000716565b949350505050565b606082471015620007795760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401620001ef565b600080866001600160a01b0316858760405162000797919062000a7b565b60006040518083038185875af1925050503d8060008114620007d6576040519150601f19603f3d011682016040523d82523d6000602084013e620007db565b606091505b509092509050620007ef87838387620007fa565b979650505050505050565b606083156200086e57825160000362000866576001600160a01b0385163b620008665760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620001ef565b50816200070e565b6200070e8383815115620008855781518083602001fd5b8060405162461bcd60e51b8152600401620001ef919062000a99565b80516001600160a01b0381168114620008b957600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620008f1578181015183820152602001620008d7565b50506000910152565b600080604083850312156200090e57600080fd5b6200091983620008a1565b60208401519092506001600160401b03808211156200093757600080fd5b818501915085601f8301126200094c57600080fd5b815181811115620009615762000961620008be565b604051601f8201601f19908116603f011681019083821181831017156200098c576200098c620008be565b81604052828152886020848701011115620009a657600080fd5b620009b9836020830160208801620008d4565b80955050505050509250929050565b60008151808452620009e2816020860160208601620008d4565b601f01601f19169290920160200192915050565b600060018060a01b03808816835260a0602084015262000a1a60a0840188620009c8565b9581166040840152938416606083015250911660809091015292915050565b60006020828403121562000a4c57600080fd5b815180151581146200047357600080fd5b60006020828403121562000a7057600080fd5b6200047382620008a1565b6000825162000a8f818460208701620008d4565b9190910192915050565b602081526000620004736020830184620009c8565b60805160a05160c05160e05161242162000b89600039600081816104d201528181610589015281816107ea0152818161121f01526112790152600081816103800152818161086d0152818161093901528181610a1c0152818161111f01528181611197015261150401526000818161076c015281816108b901528181610a6701528181610b4e01528181610bd601528181610c6101528181610cec01528181610edb015281816112d601526113ab0152600081816106590152818161082b01528181610b0201528181611240015261129a01526124216000f3fe608060405234801561001057600080fd5b50600436106102105760003560e01c80635d265d3f11610125578063ac00ff26116100ad578063d1af0c7d1161007c578063d1af0c7d146104cd578063d6968601146104f4578063f3ce280a14610507578063f887ea401461054b578063fde813a81461055e57610210565b8063ac00ff261461047a578063be17fe621461048d578063c5984847146104a0578063d19a3bb8146104b257610210565b8063797bf343116100f4578063797bf343146104265780637d9699321461042e578063950b3d73146104415780639d7fb70c14610454578063a98f92961461046757610210565b80635d265d3f146103c85780636718835f146103fe5780636c003a9b1461040b5780636c57a3dc1461041357610210565b80632d49be91116101a857806349317f1d1161017757806349317f1d146103625780634a5d09431461036a5780634cf088d91461037b5780635001f3b5146103a2578063503160d9146103b557610210565b80632d49be911461030c578063372500ab1461031f5780633d6cb5751461033c57806346aa2f121461034f57610210565b8063180cb47f116101e4578063180cb47f146102b557806318144367146102e857806327ea7fe1146102f1578063286a876b1461030457610210565b806284fc3c1461024b57806301681a621461026657806304bd4629146102795780631441a5a91461028e575b73254a93feff3beef9ca004e913bb5443754e8ab193660008037600080366000845af43d6000803e808015610244573d6000f35b3d6000fd5b005b610253610571565b6040519081526020015b60405180910390f35b610249610274366004611fe5565b610602565b610253610287366004611fe5565b5060001990565b6005546102a29062010000900461ffff1681565b60405161ffff909116815260200161025d565b6102d073feb4acf3df3cdea7399794d0869ef76a6efaff5281565b6040516001600160a01b03909116815260200161025d565b61025360015481565b6102496102ff366004612021565b610757565b610253610855565b61024961031a366004612066565b6108a4565b60055461032c9060ff1681565b604051901515815260200161025d565b61024961034a366004612066565b610923565b61025361035d366004611fe5565b610934565b6102536109d4565b600054610100900461ffff16610253565b6102d07f000000000000000000000000000000000000000000000000000000000000000081565b6002546102d0906001600160a01b031681565b6102496103c3366004612066565b6109f4565b60408051600481526024810182526020810180516001600160e01b031663440368a360e01b179052905161025d916000916120cf565b60005461032c9060ff1681565b610253610a05565b6102496104213660046120ea565b610a52565b610253610aea565b6000546301000000900461ffff16610253565b61024961044f366004612066565b610b39565b610249610462366004612066565b610bb9565b61024961047536600461210e565b610bc1565b61024961048836600461210e565b610c4c565b61024961049b366004611fe5565b610cd7565b60055461032c90610100900460ff1681565b6102d073254a93feff3beef9ca004e913bb5443754e8ab1981565b6102d07f000000000000000000000000000000000000000000000000000000000000000081565b610249610502366004612066565b610ec6565b61053761051536600461212b565b600460209081526000928352604080842090915290825290205462ffffff1681565b60405162ffffff909116815260200161025d565b6003546102d0906001600160a01b031681565b61024961056c366004612066565b610f46565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a08231906024015b602060405180830381865afa1580156105d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105fd919061215e565b905090565b3373feb4acf3df3cdea7399794d0869ef76a6efaff52146106575760405162461bcd60e51b815260040161064e9060208082526004908201526310b3b7bb60e11b604082015260600190565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316036106c15760405162461bcd60e51b815260206004820152600660248201526508585cdcd95d60d21b604482015260640161064e565b6040516370a0823160e01b81523060048201526107549073feb4acf3df3cdea7399794d0869ef76a6efaff52906001600160a01b038416906370a0823190602401602060405180830381865afa15801561071f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610743919061215e565b6001600160a01b0384169190611045565b50565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a6499060240160006040518083038186803b1580156107b657600080fd5b505afa1580156107ca573d6000803e3d6000fd5b50506005805461ff001916610100871515021790555050600254610819907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b031684611075565b600254610850906001600160a01b03167f000000000000000000000000000000000000000000000000000000000000000083611075565b505050565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a08231906024016105bc565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a6499060240160006040518083038186803b15801561090357600080fd5b505afa158015610917573d6000803e3d6000fd5b50505060019190915550565b61092b6110d0565b61075481611109565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610995573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b99190612177565b905080156109ca5750600092915050565b5060001992915050565b60006109de6110d0565b6109e6611187565b90506109f18161138d565b90565b6109fc6110d0565b610754816114db565b6040516246613160e11b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690628cc262906024016105bc565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a6499060240160006040518083038186803b158015610ab157600080fd5b505afa158015610ac5573d6000803e3d6000fd5b50506005805461ffff909416620100000263ffff000019909416939093179092555050565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a08231906024016105bc565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a6499060240160006040518083038186803b158015610b9857600080fd5b505afa158015610bac573d6000803e3d6000fd5b505050506107548161153b565b6107546110d0565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a6499060240160006040518083038186803b158015610c2057600080fd5b505afa158015610c34573d6000803e3d6000fd5b50506005805460ff1916931515939093179092555050565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a6499060240160006040518083038186803b158015610cab57600080fd5b505afa158015610cbf573d6000803e3d6000fd5b50506000805460ff1916931515939093179092555050565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a6499060240160006040518083038186803b158015610d3657600080fd5b505afa158015610d4a573d6000803e3d6000fd5b5050505073dc035d45d973e3ec169d2276ddab16f1e407384f6001600160a01b0316816001600160a01b031603610da457600280546001600160a01b03191673dc035d45d973e3ec169d2276ddab16f1e407384f17905550565b736b175474e89094c44da98b954eedeac495271d0e196001600160a01b03821601610df257600280546001600160a01b031916736b175474e89094c44da98b954eedeac495271d0f17905550565b73a0b86991c6218b36c1d19d4a2e9eb0ce3606eb47196001600160a01b03821601610e4057600280546001600160a01b03191673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4817905550565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc1196001600160a01b03821601610e8e57600280546001600160a01b03191673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc217905550565b60405162461bcd60e51b815260206004820152600d60248201526c0858985cd9481a5b881b1a5cdd609a1b604482015260640161064e565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a6499060240160006040518083038186803b158015610f2557600080fd5b505afa158015610f39573d6000803e3d6000fd5b50505050610754816115d6565b610f4e6110d0565b61075481611637565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052610fa88482611653565b611019576040516001600160a01b03841660248201526000604482015261100f90859063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526116fc565b61101984826116fc565b50505050565b6001600160a01b03163b151590565b606061103d84846000856117d1565b949350505050565b6040516001600160a01b03831660248201526044810182905261085090849063a9059cbb60e01b90606401610fd8565b6001600160a01b039283166000818152600460208181526040808420969097168352948552858220805462ffffff90951662ffffff199586168117909155908552858220928252919093529290912080549091169091179055565b3330146111075760405162461bcd60e51b815260206004820152600560248201526410b9b2b63360d91b604482015260640161064e565b565b604051632e1a7d4d60e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d906024015b600060405180830381600087803b15801561116c57600080fd5b505af1158015611180573d6000803e3d6000fd5b5050505050565b60055460009060ff16156112c8577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316633d18b9126040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156111f057600080fd5b505af1158015611204573d6000803e3d6000fd5b5050600554610100900460ff1615915061127490505761126e7f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000611267610571565b60006118ac565b506112c8565b6112c87f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006112c1610571565b6000611b4d565b60006112d2610aea565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bf86d6906040518163ffffffff1660e01b8152600401602060405180830381865afa158015611332573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113569190612177565b1561137357611363610855565b61136d90826121aa565b91505090565b606481111561138557611385816114db565b61136d610855565b60005460ff166113a757506000805460ff19166001179055565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301e1d1146040518163ffffffff1660e01b8152600401602060405180830381865afa158015611407573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142b919061215e565b9050808211156114a3576000546127109061144f90610100900461ffff16836121bd565b61145991906121d4565b61146382846121f6565b111561149f5760405162461bcd60e51b815260206004820152600b60248201526a6865616c7468436865636b60a81b604482015260640161064e565b5050565b8181111561149f57600054612710906114c7906301000000900461ffff16836121bd565b6114d191906121d4565b61146383836121f6565b6005546040516342ea02c160e01b8152600481018390526201000090910461ffff1660248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342ea02c190604401611152565b6000811161157a5760405162461bcd60e51b815260206004820152600c60248201526b085e995c9bc81c1c9bd99a5d60a21b604482015260640161064e565b61ffff8111156115b85760405162461bcd60e51b8152602060048201526009602482015268042e8dede40d0d2ced60bb1b604482015260640161064e565b6000805461ffff9092166101000262ffff0019909216919091179055565b61271081106116155760405162461bcd60e51b815260206004820152600b60248201526a085b1bdcdcc81b1a5b5a5d60aa1b604482015260640161064e565b6000805461ffff90921663010000000264ffff00000019909216919091179055565b61164881611643610855565b611be6565b905061075481611109565b6000806000846001600160a01b0316846040516116709190612209565b6000604051808303816000865af19150503d80600081146116ad576040519150601f19603f3d011682016040523d82523d6000602084013e6116b2565b606091505b50915091508180156116dc5750805115806116dc5750808060200190518101906116dc9190612177565b80156116f157506001600160a01b0385163b15155b925050505b92915050565b6000611751826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661102e9092919063ffffffff16565b90508051600014806117725750808060200190518101906117729190612177565b6108505760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161064e565b6060824710156118325760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161064e565b600080866001600160a01b0316858760405161184e9190612209565b60006040518083038185875af1925050503d806000811461188b576040519150601f19603f3d011682016040523d82523d6000602084013e611890565b606091505b50915091506118a187838387611bfe565b979650505050505050565b600060015483111561103d576003546118cf906001600160a01b03168685611c77565b6002546001600160a01b03868116911614806118f857506002546001600160a01b038581169116145b15611a155760408051610100810182526001600160a01b03878116808352878216602080850182815260009384526004808352878520938552929091528583205462ffffff9081168688019081523060608801908152426080890190815260a089018d815260c08a018d815260e08b019889526003549b5163414bf38960e01b81528b518b1698810198909852955189166024880152925190931660448601525186166064850152905160848401525160a48301525160c48201529051821660e48201529192169063414bf38990610104016020604051808303816000875af11580156119e9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0d919061215e565b91505061103d565b6001600160a01b0385811660009081526004602081815260408084206002548087168652908352818520548484528286208b881687528452948290205482516bffffffffffffffffffffffff1960608e811b8216968301969096526001600160e81b031960e898891b8116603484015293861b811660378301529190961b909116604b8601529189901b909116604e8401528051808403604201815260035461010285018352606285018281523060828701524260a287015260c286018a905260e2909501889052915163c04b8d5960e01b81529094919091169263c04b8d5992611b009201612225565b6020604051808303816000875af1158015611b1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b43919061215e565b9695505050505050565b60015482111561101957737a250d5630b4cf539739df2c5dacb4c659f2488d6338ed17398383611b7d8888611d19565b30426040518663ffffffff1660e01b8152600401611b9f95949392919061227d565b6000604051808303816000875af1158015611bbe573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111809190810190612304565b6000818310611bf55781611bf7565b825b9392505050565b60608315611c6d578251600003611c66576001600160a01b0385163b611c665760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161064e565b508161103d565b61103d8383611e8a565b604051636eb1769f60e11b81523060048201526001600160a01b03848116602483015282919084169063dd62ed3e90604401602060405180830381865afa158015611cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cea919061215e565b101561085057611d056001600160a01b038316846000611eb4565b6108506001600160a01b0383168483611eb4565b6002546060906001600160a01b03908116906000908516821480611d4e5750816001600160a01b0316846001600160a01b0316145b905080611d5c576003611d5f565b60025b60ff1667ffffffffffffffff811115611d7a57611d7a6122ee565b604051908082528060200260200182016040528015611da3578160200160208202803683370190505b5092508483600081518110611dba57611dba6123c2565b60200260200101906001600160a01b031690816001600160a01b0316815250508015611e19578383600181518110611df457611df46123c2565b60200260200101906001600160a01b031690816001600160a01b031681525050611e82565b8183600181518110611e2d57611e2d6123c2565b60200260200101906001600160a01b031690816001600160a01b0316815250508383600281518110611e6157611e616123c2565b60200260200101906001600160a01b031690816001600160a01b0316815250505b505092915050565b815115611e9a5781518083602001fd5b8060405162461bcd60e51b815260040161064e91906123d8565b801580611f2e5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611f08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f2c919061215e565b155b611f995760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606482015260840161064e565b6040516001600160a01b03831660248201526044810182905261085090849063095ea7b360e01b90606401610fd8565b80356001600160a01b0381168114611fe057600080fd5b919050565b600060208284031215611ff757600080fd5b611bf782611fc9565b801515811461075457600080fd5b803562ffffff81168114611fe057600080fd5b60008060006060848603121561203657600080fd5b833561204181612000565b925061204f6020850161200e565b915061205d6040850161200e565b90509250925092565b60006020828403121561207857600080fd5b5035919050565b60005b8381101561209a578181015183820152602001612082565b50506000910152565b600081518084526120bb81602086016020860161207f565b601f01601f19169290920160200192915050565b821515815260406020820152600061103d60408301846120a3565b6000602082840312156120fc57600080fd5b813561ffff81168114611bf757600080fd5b60006020828403121561212057600080fd5b8135611bf781612000565b6000806040838503121561213e57600080fd5b61214783611fc9565b915061215560208401611fc9565b90509250929050565b60006020828403121561217057600080fd5b5051919050565b60006020828403121561218957600080fd5b8151611bf781612000565b634e487b7160e01b600052601160045260246000fd5b808201808211156116f6576116f6612194565b80820281158282048414176116f6576116f6612194565b6000826121f157634e487b7160e01b600052601260045260246000fd5b500490565b818103818111156116f6576116f6612194565b6000825161221b81846020870161207f565b9190910192915050565b602081526000825160a0602084015261224160c08401826120a3565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b818110156122cd5784516001600160a01b0316835293830193918301916001016122a8565b50506001600160a01b03969096166060850152505050608001529392505050565b634e487b7160e01b600052604160045260246000fd5b6000602080838503121561231757600080fd5b825167ffffffffffffffff8082111561232f57600080fd5b818501915085601f83011261234357600080fd5b815181811115612355576123556122ee565b8060051b604051601f19603f8301168101818110858211171561237a5761237a6122ee565b60405291825284820192508381018501918883111561239857600080fd5b938501935b828510156123b65784518452938501939285019261239d565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b602081526000611bf760208301846120a356fea26469706673582212203457509467c4984d510102d6bae7ee98bfa314f1f9f8465165a465d6df9e0aa764736f6c634300081200330000000000000000000000000650caf159c5a49f711e8169d4336ecb9b9502750000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001b5553445320536b79205265776172647320436f6d706f756e6465720000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102105760003560e01c80635d265d3f11610125578063ac00ff26116100ad578063d1af0c7d1161007c578063d1af0c7d146104cd578063d6968601146104f4578063f3ce280a14610507578063f887ea401461054b578063fde813a81461055e57610210565b8063ac00ff261461047a578063be17fe621461048d578063c5984847146104a0578063d19a3bb8146104b257610210565b8063797bf343116100f4578063797bf343146104265780637d9699321461042e578063950b3d73146104415780639d7fb70c14610454578063a98f92961461046757610210565b80635d265d3f146103c85780636718835f146103fe5780636c003a9b1461040b5780636c57a3dc1461041357610210565b80632d49be91116101a857806349317f1d1161017757806349317f1d146103625780634a5d09431461036a5780634cf088d91461037b5780635001f3b5146103a2578063503160d9146103b557610210565b80632d49be911461030c578063372500ab1461031f5780633d6cb5751461033c57806346aa2f121461034f57610210565b8063180cb47f116101e4578063180cb47f146102b557806318144367146102e857806327ea7fe1146102f1578063286a876b1461030457610210565b806284fc3c1461024b57806301681a621461026657806304bd4629146102795780631441a5a91461028e575b73254a93feff3beef9ca004e913bb5443754e8ab193660008037600080366000845af43d6000803e808015610244573d6000f35b3d6000fd5b005b610253610571565b6040519081526020015b60405180910390f35b610249610274366004611fe5565b610602565b610253610287366004611fe5565b5060001990565b6005546102a29062010000900461ffff1681565b60405161ffff909116815260200161025d565b6102d073feb4acf3df3cdea7399794d0869ef76a6efaff5281565b6040516001600160a01b03909116815260200161025d565b61025360015481565b6102496102ff366004612021565b610757565b610253610855565b61024961031a366004612066565b6108a4565b60055461032c9060ff1681565b604051901515815260200161025d565b61024961034a366004612066565b610923565b61025361035d366004611fe5565b610934565b6102536109d4565b600054610100900461ffff16610253565b6102d07f0000000000000000000000000650caf159c5a49f711e8169d4336ecb9b95027581565b6002546102d0906001600160a01b031681565b6102496103c3366004612066565b6109f4565b60408051600481526024810182526020810180516001600160e01b031663440368a360e01b179052905161025d916000916120cf565b60005461032c9060ff1681565b610253610a05565b6102496104213660046120ea565b610a52565b610253610aea565b6000546301000000900461ffff16610253565b61024961044f366004612066565b610b39565b610249610462366004612066565b610bb9565b61024961047536600461210e565b610bc1565b61024961048836600461210e565b610c4c565b61024961049b366004611fe5565b610cd7565b60055461032c90610100900460ff1681565b6102d073254a93feff3beef9ca004e913bb5443754e8ab1981565b6102d07f00000000000000000000000056072c95faa701256059aa122697b133aded927981565b610249610502366004612066565b610ec6565b61053761051536600461212b565b600460209081526000928352604080842090915290825290205462ffffff1681565b60405162ffffff909116815260200161025d565b6003546102d0906001600160a01b031681565b61024961056c366004612066565b610f46565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000056072c95faa701256059aa122697b133aded92796001600160a01b0316906370a08231906024015b602060405180830381865afa1580156105d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105fd919061215e565b905090565b3373feb4acf3df3cdea7399794d0869ef76a6efaff52146106575760405162461bcd60e51b815260040161064e9060208082526004908201526310b3b7bb60e11b604082015260600190565b60405180910390fd5b7f000000000000000000000000dc035d45d973e3ec169d2276ddab16f1e407384f6001600160a01b0316816001600160a01b0316036106c15760405162461bcd60e51b815260206004820152600660248201526508585cdcd95d60d21b604482015260640161064e565b6040516370a0823160e01b81523060048201526107549073feb4acf3df3cdea7399794d0869ef76a6efaff52906001600160a01b038416906370a0823190602401602060405180830381865afa15801561071f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610743919061215e565b6001600160a01b0384169190611045565b50565b6040516348e4a64960e01b81523360048201527f0000000000000000000000000868076663bbc6638cedd27704cc8f0fa53d5b816001600160a01b0316906348e4a6499060240160006040518083038186803b1580156107b657600080fd5b505afa1580156107ca573d6000803e3d6000fd5b50506005805461ff001916610100871515021790555050600254610819907f00000000000000000000000056072c95faa701256059aa122697b133aded9279906001600160a01b031684611075565b600254610850906001600160a01b03167f000000000000000000000000dc035d45d973e3ec169d2276ddab16f1e407384f83611075565b505050565b6040516370a0823160e01b81523060048201526000907f0000000000000000000000000650caf159c5a49f711e8169d4336ecb9b9502756001600160a01b0316906370a08231906024016105bc565b6040516348e4a64960e01b81523360048201527f0000000000000000000000000868076663bbc6638cedd27704cc8f0fa53d5b816001600160a01b0316906348e4a6499060240160006040518083038186803b15801561090357600080fd5b505afa158015610917573d6000803e3d6000fd5b50505060019190915550565b61092b6110d0565b61075481611109565b6000807f0000000000000000000000000650caf159c5a49f711e8169d4336ecb9b9502756001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610995573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b99190612177565b905080156109ca5750600092915050565b5060001992915050565b60006109de6110d0565b6109e6611187565b90506109f18161138d565b90565b6109fc6110d0565b610754816114db565b6040516246613160e11b81523060048201526000907f0000000000000000000000000650caf159c5a49f711e8169d4336ecb9b9502756001600160a01b031690628cc262906024016105bc565b6040516348e4a64960e01b81523360048201527f0000000000000000000000000868076663bbc6638cedd27704cc8f0fa53d5b816001600160a01b0316906348e4a6499060240160006040518083038186803b158015610ab157600080fd5b505afa158015610ac5573d6000803e3d6000fd5b50506005805461ffff909416620100000263ffff000019909416939093179092555050565b6040516370a0823160e01b81523060048201526000907f000000000000000000000000dc035d45d973e3ec169d2276ddab16f1e407384f6001600160a01b0316906370a08231906024016105bc565b6040516348e4a64960e01b81523360048201527f0000000000000000000000000868076663bbc6638cedd27704cc8f0fa53d5b816001600160a01b0316906348e4a6499060240160006040518083038186803b158015610b9857600080fd5b505afa158015610bac573d6000803e3d6000fd5b505050506107548161153b565b6107546110d0565b6040516348e4a64960e01b81523360048201527f0000000000000000000000000868076663bbc6638cedd27704cc8f0fa53d5b816001600160a01b0316906348e4a6499060240160006040518083038186803b158015610c2057600080fd5b505afa158015610c34573d6000803e3d6000fd5b50506005805460ff1916931515939093179092555050565b6040516348e4a64960e01b81523360048201527f0000000000000000000000000868076663bbc6638cedd27704cc8f0fa53d5b816001600160a01b0316906348e4a6499060240160006040518083038186803b158015610cab57600080fd5b505afa158015610cbf573d6000803e3d6000fd5b50506000805460ff1916931515939093179092555050565b6040516348e4a64960e01b81523360048201527f0000000000000000000000000868076663bbc6638cedd27704cc8f0fa53d5b816001600160a01b0316906348e4a6499060240160006040518083038186803b158015610d3657600080fd5b505afa158015610d4a573d6000803e3d6000fd5b5050505073dc035d45d973e3ec169d2276ddab16f1e407384f6001600160a01b0316816001600160a01b031603610da457600280546001600160a01b03191673dc035d45d973e3ec169d2276ddab16f1e407384f17905550565b736b175474e89094c44da98b954eedeac495271d0e196001600160a01b03821601610df257600280546001600160a01b031916736b175474e89094c44da98b954eedeac495271d0f17905550565b73a0b86991c6218b36c1d19d4a2e9eb0ce3606eb47196001600160a01b03821601610e4057600280546001600160a01b03191673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4817905550565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc1196001600160a01b03821601610e8e57600280546001600160a01b03191673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc217905550565b60405162461bcd60e51b815260206004820152600d60248201526c0858985cd9481a5b881b1a5cdd609a1b604482015260640161064e565b6040516348e4a64960e01b81523360048201527f0000000000000000000000000868076663bbc6638cedd27704cc8f0fa53d5b816001600160a01b0316906348e4a6499060240160006040518083038186803b158015610f2557600080fd5b505afa158015610f39573d6000803e3d6000fd5b50505050610754816115d6565b610f4e6110d0565b61075481611637565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052610fa88482611653565b611019576040516001600160a01b03841660248201526000604482015261100f90859063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526116fc565b61101984826116fc565b50505050565b6001600160a01b03163b151590565b606061103d84846000856117d1565b949350505050565b6040516001600160a01b03831660248201526044810182905261085090849063a9059cbb60e01b90606401610fd8565b6001600160a01b039283166000818152600460208181526040808420969097168352948552858220805462ffffff90951662ffffff199586168117909155908552858220928252919093529290912080549091169091179055565b3330146111075760405162461bcd60e51b815260206004820152600560248201526410b9b2b63360d91b604482015260640161064e565b565b604051632e1a7d4d60e01b8152600481018290527f0000000000000000000000000650caf159c5a49f711e8169d4336ecb9b9502756001600160a01b031690632e1a7d4d906024015b600060405180830381600087803b15801561116c57600080fd5b505af1158015611180573d6000803e3d6000fd5b5050505050565b60055460009060ff16156112c8577f0000000000000000000000000650caf159c5a49f711e8169d4336ecb9b9502756001600160a01b0316633d18b9126040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156111f057600080fd5b505af1158015611204573d6000803e3d6000fd5b5050600554610100900460ff1615915061127490505761126e7f00000000000000000000000056072c95faa701256059aa122697b133aded92797f000000000000000000000000dc035d45d973e3ec169d2276ddab16f1e407384f611267610571565b60006118ac565b506112c8565b6112c87f00000000000000000000000056072c95faa701256059aa122697b133aded92797f000000000000000000000000dc035d45d973e3ec169d2276ddab16f1e407384f6112c1610571565b6000611b4d565b60006112d2610aea565b90507f0000000000000000000000000868076663bbc6638cedd27704cc8f0fa53d5b816001600160a01b031663bf86d6906040518163ffffffff1660e01b8152600401602060405180830381865afa158015611332573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113569190612177565b1561137357611363610855565b61136d90826121aa565b91505090565b606481111561138557611385816114db565b61136d610855565b60005460ff166113a757506000805460ff19166001179055565b60007f0000000000000000000000000868076663bbc6638cedd27704cc8f0fa53d5b816001600160a01b03166301e1d1146040518163ffffffff1660e01b8152600401602060405180830381865afa158015611407573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142b919061215e565b9050808211156114a3576000546127109061144f90610100900461ffff16836121bd565b61145991906121d4565b61146382846121f6565b111561149f5760405162461bcd60e51b815260206004820152600b60248201526a6865616c7468436865636b60a81b604482015260640161064e565b5050565b8181111561149f57600054612710906114c7906301000000900461ffff16836121bd565b6114d191906121d4565b61146383836121f6565b6005546040516342ea02c160e01b8152600481018390526201000090910461ffff1660248201527f0000000000000000000000000650caf159c5a49f711e8169d4336ecb9b9502756001600160a01b0316906342ea02c190604401611152565b6000811161157a5760405162461bcd60e51b815260206004820152600c60248201526b085e995c9bc81c1c9bd99a5d60a21b604482015260640161064e565b61ffff8111156115b85760405162461bcd60e51b8152602060048201526009602482015268042e8dede40d0d2ced60bb1b604482015260640161064e565b6000805461ffff9092166101000262ffff0019909216919091179055565b61271081106116155760405162461bcd60e51b815260206004820152600b60248201526a085b1bdcdcc81b1a5b5a5d60aa1b604482015260640161064e565b6000805461ffff90921663010000000264ffff00000019909216919091179055565b61164881611643610855565b611be6565b905061075481611109565b6000806000846001600160a01b0316846040516116709190612209565b6000604051808303816000865af19150503d80600081146116ad576040519150601f19603f3d011682016040523d82523d6000602084013e6116b2565b606091505b50915091508180156116dc5750805115806116dc5750808060200190518101906116dc9190612177565b80156116f157506001600160a01b0385163b15155b925050505b92915050565b6000611751826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661102e9092919063ffffffff16565b90508051600014806117725750808060200190518101906117729190612177565b6108505760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161064e565b6060824710156118325760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161064e565b600080866001600160a01b0316858760405161184e9190612209565b60006040518083038185875af1925050503d806000811461188b576040519150601f19603f3d011682016040523d82523d6000602084013e611890565b606091505b50915091506118a187838387611bfe565b979650505050505050565b600060015483111561103d576003546118cf906001600160a01b03168685611c77565b6002546001600160a01b03868116911614806118f857506002546001600160a01b038581169116145b15611a155760408051610100810182526001600160a01b03878116808352878216602080850182815260009384526004808352878520938552929091528583205462ffffff9081168688019081523060608801908152426080890190815260a089018d815260c08a018d815260e08b019889526003549b5163414bf38960e01b81528b518b1698810198909852955189166024880152925190931660448601525186166064850152905160848401525160a48301525160c48201529051821660e48201529192169063414bf38990610104016020604051808303816000875af11580156119e9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0d919061215e565b91505061103d565b6001600160a01b0385811660009081526004602081815260408084206002548087168652908352818520548484528286208b881687528452948290205482516bffffffffffffffffffffffff1960608e811b8216968301969096526001600160e81b031960e898891b8116603484015293861b811660378301529190961b909116604b8601529189901b909116604e8401528051808403604201815260035461010285018352606285018281523060828701524260a287015260c286018a905260e2909501889052915163c04b8d5960e01b81529094919091169263c04b8d5992611b009201612225565b6020604051808303816000875af1158015611b1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b43919061215e565b9695505050505050565b60015482111561101957737a250d5630b4cf539739df2c5dacb4c659f2488d6338ed17398383611b7d8888611d19565b30426040518663ffffffff1660e01b8152600401611b9f95949392919061227d565b6000604051808303816000875af1158015611bbe573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111809190810190612304565b6000818310611bf55781611bf7565b825b9392505050565b60608315611c6d578251600003611c66576001600160a01b0385163b611c665760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161064e565b508161103d565b61103d8383611e8a565b604051636eb1769f60e11b81523060048201526001600160a01b03848116602483015282919084169063dd62ed3e90604401602060405180830381865afa158015611cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cea919061215e565b101561085057611d056001600160a01b038316846000611eb4565b6108506001600160a01b0383168483611eb4565b6002546060906001600160a01b03908116906000908516821480611d4e5750816001600160a01b0316846001600160a01b0316145b905080611d5c576003611d5f565b60025b60ff1667ffffffffffffffff811115611d7a57611d7a6122ee565b604051908082528060200260200182016040528015611da3578160200160208202803683370190505b5092508483600081518110611dba57611dba6123c2565b60200260200101906001600160a01b031690816001600160a01b0316815250508015611e19578383600181518110611df457611df46123c2565b60200260200101906001600160a01b031690816001600160a01b031681525050611e82565b8183600181518110611e2d57611e2d6123c2565b60200260200101906001600160a01b031690816001600160a01b0316815250508383600281518110611e6157611e616123c2565b60200260200101906001600160a01b031690816001600160a01b0316815250505b505092915050565b815115611e9a5781518083602001fd5b8060405162461bcd60e51b815260040161064e91906123d8565b801580611f2e5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611f08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f2c919061215e565b155b611f995760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606482015260840161064e565b6040516001600160a01b03831660248201526044810182905261085090849063095ea7b360e01b90606401610fd8565b80356001600160a01b0381168114611fe057600080fd5b919050565b600060208284031215611ff757600080fd5b611bf782611fc9565b801515811461075457600080fd5b803562ffffff81168114611fe057600080fd5b60008060006060848603121561203657600080fd5b833561204181612000565b925061204f6020850161200e565b915061205d6040850161200e565b90509250925092565b60006020828403121561207857600080fd5b5035919050565b60005b8381101561209a578181015183820152602001612082565b50506000910152565b600081518084526120bb81602086016020860161207f565b601f01601f19169290920160200192915050565b821515815260406020820152600061103d60408301846120a3565b6000602082840312156120fc57600080fd5b813561ffff81168114611bf757600080fd5b60006020828403121561212057600080fd5b8135611bf781612000565b6000806040838503121561213e57600080fd5b61214783611fc9565b915061215560208401611fc9565b90509250929050565b60006020828403121561217057600080fd5b5051919050565b60006020828403121561218957600080fd5b8151611bf781612000565b634e487b7160e01b600052601160045260246000fd5b808201808211156116f6576116f6612194565b80820281158282048414176116f6576116f6612194565b6000826121f157634e487b7160e01b600052601260045260246000fd5b500490565b818103818111156116f6576116f6612194565b6000825161221b81846020870161207f565b9190910192915050565b602081526000825160a0602084015261224160c08401826120a3565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b818110156122cd5784516001600160a01b0316835293830193918301916001016122a8565b50506001600160a01b03969096166060850152505050608001529392505050565b634e487b7160e01b600052604160045260246000fd5b6000602080838503121561231757600080fd5b825167ffffffffffffffff8082111561232f57600080fd5b818501915085601f83011261234357600080fd5b815181811115612355576123556122ee565b8060051b604051601f19603f8301168101818110858211171561237a5761237a6122ee565b60405291825284820192508381018501918883111561239857600080fd5b938501935b828510156123b65784518452938501939285019261239d565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b602081526000611bf760208301846120a356fea26469706673582212203457509467c4984d510102d6bae7ee98bfa314f1f9f8465165a465d6df9e0aa764736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000650caf159c5a49f711e8169d4336ecb9b9502750000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001b5553445320536b79205265776172647320436f6d706f756e6465720000000000
-----Decoded View---------------
Arg [0] : _staking (address): 0x0650CAF159C5A49f711e8169D4336ECB9b950275
Arg [1] : _name (string): USDS Sky Rewards Compounder
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000000650caf159c5a49f711e8169d4336ecb9b950275
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [2] : 000000000000000000000000000000000000000000000000000000000000001b
Arg [3] : 5553445320536b79205265776172647320436f6d706f756e6465720000000000
Deployed Bytecode Sourcemap
96283:7221:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41522:42;56977:14;56730:33;;56958:34;57231:1;57212;57180:14;57161:1;57118:25;57095:5;57065:181;57316:16;57313:1;57310;57295:38;57420:6;57439:66;;;;57554:16;57551:1;57544:27;57439:66;57474:16;57471:1;57464:27;57413:172;;100420:126;;;:::i;:::-;;;160:25:1;;;148:2;133:18;100420:126:0;;;;;;;;103212:196;;;;;;:::i;:::-;;:::i;50628:145::-;;;;;;:::i;:::-;-1:-1:-1;;;50749:17:0;50628:145;96694:29;;;;;;;;;;;;;;;739:6:1;727:19;;;709:38;;697:2;682:18;96694:29:0;565:188:1;96762:72:0;;96792:42;96762:72;;;;;-1:-1:-1;;;;;922:32:1;;;904:51;;892:2;877:18;96762:72:0;758:203:1;89587:30:0;;;;;;101376:261;;;;;;:::i;:::-;;:::i;100287:127::-;;;:::i;101782:129::-;;;;;;:::i;:::-;;:::i;96456:31::-;;;;;;;;;;;;1995:14:1;;1988:22;1970:41;;1958:2;1943:18;96456:31:0;1830:187:1;53114:98:0;;;;;;:::i;:::-;;:::i;99068:211::-;;;;;;:::i;:::-;;:::i;61473:308::-;;;:::i;59108:99::-;59157:7;59183:17;;;;;;59108:99;;96844:32;;;;;89659:64;;;;;-1:-1:-1;;;;;89659:64:0;;;52544:102;;;;;;:::i;:::-;;:::i;48380:311::-;48618:56;;;;;;;;;;;;;;;;-1:-1:-1;;;;;48618:56:0;-1:-1:-1;;;48618:56:0;;;48380:311;;;;-1:-1:-1;;48380:311:0;:::i;58565:32::-;;;;;;;;;100552:121;;;:::i;102657:100::-;;;;;;:::i;:::-;;:::i;100171:110::-;;;:::i;59393:95::-;59440:7;59466:15;;;;;;59393:95;;59676:156;;;;;;:::i;:::-;;:::i;54400:98::-;;;;;;:::i;:::-;;:::i;101063:114::-;;;;;;:::i;:::-;;:::i;61196:116::-;;;;;;:::i;:::-;;:::i;102178:362::-;;;;;;:::i;:::-;;:::i;96630:20::-;;;;;;;;;;;;41463:101;;41522:42;41463:101;;96882:37;;;;;60470:148;;;;;;:::i;:::-;;:::i;90029:61::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3817:8:1;3805:21;;;3787:40;;3775:2;3760:18;90029:61:0;3643:190:1;89779:66:0;;;;;-1:-1:-1;;;;;89779:66:0;;;55013:113;;;;;;:::i;:::-;;:::i;100420:126::-;100495:44;;-1:-1:-1;;;100495:44:0;;100533:4;100495:44;;;904:51:1;100469:7:0;;100501:12;-1:-1:-1;;;;;100495:29:0;;;;877:18:1;;100495:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;100488:51;;100420:126;:::o;103212:196::-;103458:10;96792:42;103458:17;103450:34;;;;-1:-1:-1;;;103450:34:0;;;;;;4229:2:1;4211:21;;;4268:1;4248:18;;;4241:29;-1:-1:-1;;;4301:2:1;4286:18;;4279:34;4345:2;4330:18;;4027:327;103450:34:0;;;;;;;;;103303:5:::1;-1:-1:-1::0;;;;;103285:24:0::1;:6;-1:-1:-1::0;;;;;103285:24:0::1;::::0;103277:43:::1;;;::::0;-1:-1:-1;;;103277:43:0;;4561:2:1;103277:43:0::1;::::0;::::1;4543:21:1::0;4600:1;4580:18;;;4573:29;-1:-1:-1;;;4618:18:1;;;4611:36;4664:18;;103277:43:0::1;4359:329:1::0;103277:43:0::1;103362:38;::::0;-1:-1:-1;;;103362:38:0;;103394:4:::1;103362:38;::::0;::::1;904:51:1::0;103330:71:0::1;::::0;96792:42:::1;::::0;-1:-1:-1;;;;;103362:23:0;::::1;::::0;::::1;::::0;877:18:1;;103362:38:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;103330:26:0;::::1;::::0;:71;:26:::1;:71::i;:::-;103212:196:::0;:::o;101376:261::-;39969:47;;-1:-1:-1;;;39969:47:0;;40005:10;39969:47;;;904:51:1;39969:17:0;-1:-1:-1;;;;;39969:35:0;;;;877:18:1;;39969:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;101497:8:0::1;:20:::0;;-1:-1:-1;;101497:20:0::1;;::::0;::::1;;;;::::0;;-1:-1:-1;;101553:4:0::1;::::0;101527:46:::1;::::0;101539:12:::1;::::0;-1:-1:-1;;;;;101553:4:0::1;101559:13:::0;101527:11:::1;:46::i;:::-;101595:4;::::0;101583:47:::1;::::0;-1:-1:-1;;;;;101595:4:0::1;101609:5;101617:12:::0;101583:11:::1;:47::i;:::-;101376:261:::0;;;:::o;100287:127::-;100368:39;;-1:-1:-1;;;100368:39:0;;100401:4;100368:39;;;904:51:1;100334:15:0;;100374:7;-1:-1:-1;;;;;100368:24:0;;;;877:18:1;;100368:39:0;758:203:1;101782:129:0;39969:47;;-1:-1:-1;;;39969:47:0;;40005:10;39969:47;;;904:51:1;39969:17:0;-1:-1:-1;;;;;39969:35:0;;;;877:18:1;;39969:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;101870:15:0::1;:34:::0;;;;-1:-1:-1;101782:129:0:o;53114:98::-;39800:11;:9;:11::i;:::-;53186:19:::1;53197:7;53186:10;:19::i;99068:211::-:0;99149:7;99168:11;99191:7;-1:-1:-1;;;;;99182:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;99168:40;;99222:6;99218:20;;;-1:-1:-1;99237:1:0;;99068:211;-1:-1:-1;;99068:211:0:o;99218:20::-;-1:-1:-1;;;99255:17:0;99068:211;-1:-1:-1;;99068:211:0:o;61473:308::-;61569:20;39800:11;:9;:11::i;:::-;61656:19:::1;:17;:19::i;:::-;61641:34;;61741:33;61761:12;61741:19;:33::i;:::-;61473:308:::0;:::o;52544:102::-;39800:11;:9;:11::i;:::-;52618:21:::1;52631:7;52618:12;:21::i;100552:121::-:0;100627:39;;-1:-1:-1;;;100627:39:0;;100660:4;100627:39;;;904:51:1;100601:7:0;;100636;-1:-1:-1;;;;;100627:24:0;;;;877:18:1;;100627:39:0;758:203:1;102657:100:0;39969:47;;-1:-1:-1;;;39969:47:0;;40005:10;39969:47;;;904:51:1;39969:17:0;-1:-1:-1;;;;;39969:35:0;;;;877:18:1;;39969:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;102730:8:0::1;:20:::0;;::::1;::::0;;::::1;::::0;::::1;-1:-1:-1::0;;102730:20:0;;::::1;::::0;;;::::1;::::0;;;-1:-1:-1;;102657:100:0:o;100171:110::-;100244:30;;-1:-1:-1;;;100244:30:0;;100268:4;100244:30;;;904:51:1;100218:7:0;;100244:5;-1:-1:-1;;;;;100244:15:0;;;;877:18:1;;100244:30:0;758:203:1;59676:156:0;39969:47;;-1:-1:-1;;;39969:47:0;;40005:10;39969:47;;;904:51:1;39969:17:0;-1:-1:-1;;;;;39969:35:0;;;;877:18:1;;39969:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59783:42:::1;59804:20;59783;:42::i;54400:98::-:0;39800:11;:9;:11::i;101063:114::-;39969:47;;-1:-1:-1;;;39969:47:0;;40005:10;39969:47;;;904:51:1;39969:17:0;-1:-1:-1;;;;;39969:35:0;;;;877:18:1;;39969:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;101142:12:0::1;:28:::0;;-1:-1:-1;;101142:28:0::1;::::0;::::1;;::::0;;;::::1;::::0;;;-1:-1:-1;;101063:114:0:o;61196:116::-;39969:47;;-1:-1:-1;;;39969:47:0;;40005:10;39969:47;;;904:51:1;39969:17:0;-1:-1:-1;;;;;39969:35:0;;;;877:18:1;;39969:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;61275:13:0::1;:30:::0;;-1:-1:-1;;61275:30:0::1;::::0;::::1;;::::0;;;::::1;::::0;;;-1:-1:-1;;61196:116:0:o;102178:362::-;39969:47;;-1:-1:-1;;;39969:47:0;;40005:10;39969:47;;;904:51:1;39969:17:0;-1:-1:-1;;;;;39969:35:0;;;;877:18:1;;39969:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97103:42:::1;-1:-1:-1::0;;;;;102248:13:0::1;:5;-1:-1:-1::0;;;;;102248:13:0::1;::::0;102244:290:::1;;102277:4;:11:::0;;-1:-1:-1;;;;;;102277:11:0::1;97103:42;102277:11;::::0;;103212:196;:::o;102244:290::-:1;-1:-1:-1::0;;;;;;;102309:12:0;::::1;::::0;102305:229:::1;;102337:4;:10:::0;;-1:-1:-1;;;;;;102337:10:0::1;97182:42;102337:10;::::0;;103212:196;:::o;102305:229::-:1;-1:-1:-1::0;;;;;;;102368:13:0;::::1;::::0;102364:170:::1;;102397:4;:11:::0;;-1:-1:-1;;;;;;102397:11:0::1;97262:42;102397:11;::::0;;103212:196;:::o;102364:170::-:1;-1:-1:-1::0;;;;;;;102429:13:0;::::1;::::0;102425:109:::1;;102458:4;:11:::0;;-1:-1:-1;;;;;;102458:11:0::1;97342:42;102458:11;::::0;;103212:196;:::o;102425:109::-:1;102500:23;::::0;-1:-1:-1;;;102500:23:0;;5145:2:1;102500:23:0::1;::::0;::::1;5127:21:1::0;5184:2;5164:18;;;5157:30;-1:-1:-1;;;5203:18:1;;;5196:43;5256:18;;102500:23:0::1;4943:337:1::0;60470:148:0;39969:47;;-1:-1:-1;;;39969:47:0;;40005:10;39969:47;;;904:51:1;39969:17:0;-1:-1:-1;;;;;39969:35:0;;;;877:18:1;;39969:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60573:38:::1;60592:18;60573;:38::i;55013:113::-:0;39800:11;:9;:11::i;:::-;55092:27:::1;55111:7;55092:18;:27::i;75822:410::-:0;75937:62;;;-1:-1:-1;;;;;5477:32:1;;75937:62:0;;;5459:51:1;5526:18;;;;5519:34;;;75937:62:0;;;;;;;;;;5432:18:1;;;;75937:62:0;;;;;;;;-1:-1:-1;;;;;75937:62:0;-1:-1:-1;;;75937:62:0;;;76015:44;76039:5;75937:62;76015:23;:44::i;:::-;76010:216;;76102:58;;-1:-1:-1;;;;;5762:32:1;;76102:58:0;;;5744:51:1;76158:1:0;5811:18:1;;;5804:45;76075:86:0;;76095:5;;-1:-1:-1;;;76125:22:0;5717:18:1;;76102:58:0;;;;-1:-1:-1;;76102:58:0;;;;;;;;;;;;;;-1:-1:-1;;;;;76102:58:0;-1:-1:-1;;;;;;76102:58:0;;;;;;;;;;76075:19;:86::i;:::-;76175:40;76195:5;76202:12;76175:19;:40::i;:::-;75899:333;75822:410;;;:::o;64333:320::-;-1:-1:-1;;;;;64623:19:0;;:23;;;64333:320::o;67029:223::-;67162:12;67193:52;67215:6;67223:4;67229:1;67232:12;67193:21;:52::i;:::-;67186:59;67029:223;-1:-1:-1;;;;67029:223:0:o;72984:175::-;73093:58;;-1:-1:-1;;;;;5477:32:1;;73093:58:0;;;5459:51:1;5526:18;;;5519:34;;;73066:86:0;;73086:5;;-1:-1:-1;;;73116:23:0;5432:18:1;;73093:58:0;5285:274:1;90390:206:0;-1:-1:-1;;;;;90515:16:0;;;;;;;:7;:16;;;;;;;;:25;;;;;;;;;;;;:32;;;;;;-1:-1:-1;;90515:32:0;;;;;;;;90557:16;;;;;;:25;;;;;;;;;;;:32;;;;;;;;;;90390:206::o;40611:97::-;40664:10;40686:4;40664:27;40656:45;;;;-1:-1:-1;;;40656:45:0;;6062:2:1;40656:45:0;;;6044:21:1;6101:1;6081:18;;;6074:29;-1:-1:-1;;;6119:18:1;;;6112:35;6164:18;;40656:45:0;5860:328:1;40656:45:0;40611:97::o;98119:107::-;98184:35;;-1:-1:-1;;;98184:35:0;;;;;160:25:1;;;98193:7:0;-1:-1:-1;;;;;98184:26:0;;;;133:18:1;;98184:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;98119:107;:::o;98232:830::-;98324:12;;98288:20;;98324:12;;98320:425;;;98361:7;-1:-1:-1;;;;;98352:27:0;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;98399:8:0;;;;;;;98395:327;;-1:-1:-1;98395:327:0;;-1:-1:-1;98395:327:0;98436:62;98446:12;98468:5;98476:18;:16;:18::i;:::-;98496:1;98436:9;:62::i;:::-;;98395:327;;;98593:67;98608:12;98630:5;98638:18;:16;:18::i;:::-;98658:1;98593:14;:67::i;:::-;98755:15;98773:16;:14;:16::i;:::-;98755:34;;98803:17;-1:-1:-1;;;;;98803:28:0;;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;98799:257;;;98874:16;:14;:16::i;:::-;98864:26;;:7;:26;:::i;:::-;98849:41;;98310:752;98232:830;:::o;98799:257::-;97429:3;98925:7;:20;98921:80;;;98965:21;98978:7;98965:12;:21::i;:::-;99029:16;:14;:16::i;62001:890::-;62087:13;;;;62082:85;;-1:-1:-1;62116:13:0;:20;;-1:-1:-1;;62116:20:0;62132:4;62116:20;;;62001:890::o;62082:85::-;62242:26;62271:17;-1:-1:-1;;;;;62271:29:0;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;62242:60;;62335:18;62317:15;:36;62313:572;;;62487:17;;58640:6;;62458:47;;62487:17;;;;;62458:18;:47;:::i;:::-;62457:83;;;;:::i;:::-;62396:36;62414:18;62396:15;:36;:::i;:::-;62395:145;;62369:217;;;;-1:-1:-1;;;62369:217:0;;7185:2:1;62369:217:0;;;7167:21:1;7224:2;7204:18;;;7197:30;-1:-1:-1;;;7243:18:1;;;7236:41;7294:18;;62369:217:0;6983:335:1;62369:217:0;62072:819;62001:890;:::o;62313:572::-;62628:15;62607:18;:36;62603:282;;;62776:15;;58640:6;;62747:45;;62776:15;;;;;62747:18;:45;:::i;:::-;62746:81;;;;:::i;:::-;62685:36;62706:15;62685:18;:36;:::i;97997:116::-;98097:8;;98064:42;;-1:-1:-1;;;98064:42:0;;;;;7495:25:1;;;98097:8:0;;;;;;7536:18:1;;;7529:47;98073:7:0;-1:-1:-1;;;;;98064:23:0;;;;7468:18:1;;98064:42:0;7323:259:1;60023:265:0;60133:1;60110:20;:24;60102:49;;;;-1:-1:-1;;;60102:49:0;;7789:2:1;60102:49:0;;;7771:21:1;7828:2;7808:18;;;7801:30;-1:-1:-1;;;7847:18:1;;;7840:42;7899:18;;60102:49:0;7587:336:1;60102:49:0;60193:16;60169:40;;;60161:62;;;;-1:-1:-1;;;60161:62:0;;8130:2:1;60161:62:0;;;8112:21:1;8169:1;8149:18;;;8142:29;-1:-1:-1;;;8187:18:1;;;8180:39;8236:18;;60161:62:0;7928:332:1;60161:62:0;60233:17;:48;;;;;;;;-1:-1:-1;;60233:48:0;;;;;;;;;60023:265::o;60803:188::-;58640:6;60886:18;:28;60878:52;;;;-1:-1:-1;;;60878:52:0;;8467:2:1;60878:52:0;;;8449:21:1;8506:2;8486:18;;;8479:30;-1:-1:-1;;;8525:18:1;;;8518:41;8576:18;;60878:52:0;8265:335:1;60878:52:0;60940:15;:44;;;;;;;;-1:-1:-1;;60940:44:0;;;;;;;;;60803:188::o;102763:150::-;102846:31;102851:7;102860:16;:14;:16::i;:::-;102846:4;:31::i;:::-;102836:41;;102887:19;102898:7;102887:10;:19::i;78382:594::-;78465:4;78767:12;78781:23;78816:5;-1:-1:-1;;;;;78808:19:0;78828:4;78808:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;78766:67;;;;78862:7;:69;;;;-1:-1:-1;78874:17:0;;:22;;:56;;;78911:10;78900:30;;;;;;;;;;;;:::i;:::-;78862:107;;;;-1:-1:-1;;;;;;64623:19:0;;;:23;;78935:34;78843:126;;;;78382:594;;;;;:::o;77239:642::-;77658:23;77684:69;77712:4;77684:69;;;;;;;;;;;;;;;;;77692:5;-1:-1:-1;;;;;77684:27:0;;;:69;;;;;:::i;:::-;77658:95;;77771:10;:17;77792:1;77771:22;:56;;;;77808:10;77797:30;;;;;;;;;;;;:::i;:::-;77763:111;;;;-1:-1:-1;;;77763:111:0;;9099:2:1;77763:111:0;;;9081:21:1;9138:2;9118:18;;;9111:30;9177:34;9157:18;;;9150:62;-1:-1:-1;;;9228:18:1;;;9221:40;9278:19;;77763:111:0;8897:406:1;68086:446:0;68251:12;68308:5;68283:21;:30;;68275:81;;;;-1:-1:-1;;;68275:81:0;;9510:2:1;68275:81:0;;;9492:21:1;9549:2;9529:18;;;9522:30;9588:34;9568:18;;;9561:62;-1:-1:-1;;;9639:18:1;;;9632:36;9685:19;;68275:81:0;9308:402:1;68275:81:0;68367:12;68381:23;68408:6;-1:-1:-1;;;;;68408:11:0;68427:5;68434:4;68408:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68366:73;;;;68456:69;68483:6;68491:7;68500:10;68512:12;68456:26;:69::i;:::-;68449:76;68086:446;-1:-1:-1;;;;;;;68086:446:0:o;91370:1625::-;91523:18;91569:15;;91557:9;:27;91553:1436;;;91616:6;;91600:41;;-1:-1:-1;;;;;91616:6:0;91624:5;91631:9;91600:15;:41::i;:::-;91668:4;;-1:-1:-1;;;;;91659:13:0;;;91668:4;;91659:13;;:28;;-1:-1:-1;91683:4:0;;-1:-1:-1;;;;;91676:11:0;;;91683:4;;91676:11;91659:28;91655:1324;;;91758:472;;;;;;;;-1:-1:-1;;;;;91758:472:0;;;;;;;;;;;;;;;;-1:-1:-1;91922:14:0;;;:7;:14;;;;;;:19;;;;;;;;;;;;;;;91758:472;;;;;;91990:4;91758:472;;;;;;92034:15;91758:472;;;;;;;;;;;;;;;;;;;;;;;;92274:6;;92262:44;;-1:-1:-1;;;92262:44:0;;10002:13:1;;9998:22;;92262:44:0;;;9980:41:1;;;;10063:24;;10059:33;;10037:20;;;10030:63;10135:24;;10131:39;;;10109:20;;;10102:69;10213:24;10209:33;;10187:20;;;10180:63;10281:24;;10259:20;;;10252:54;10344:24;10322:20;;;10315:54;10407:24;10385:20;;;10378:54;10474:24;;10470:33;;10448:20;;;10441:63;91758:472:0;;92274:6;;92262:36;;9914:19:1;;92262:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92249:57;;91689:632;91655:1324;;;-1:-1:-1;;;;;92441:14:0;;;92345:17;92441:14;;;:7;:14;;;;;;;;92456:4;;;;;92441:20;;;;;;;;;92540:13;;;;;;:18;;;;;;;;;;;;92365:263;;-1:-1:-1;;10822:2:1;10818:15;;;10814:24;;92365:263:0;;;10802:37:1;;;;-1:-1:-1;;;;;;10862:3:1;10910:16;;;;;10892:12;;;10885:47;10966:15;;;;;10948:12;;;10941:46;11021:16;;;;;;;11003:12;;;10996:47;11077:15;;;;11073:24;;;11059:12;;;11052:46;92365:263:0;;;;;;;;;92672:6;;92712:234;;;;;11114:12:1;;;92712:234:0;;;92804:4;92712:234;;;;92835:15;92712:234;;;;;;;;;;;;;;;;;92660:304;;-1:-1:-1;;;92660:304:0;;92365:263;;92672:6;;;;;92660:30;;:304;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92647:317;91370:1625;-1:-1:-1;;;;;;91370:1625:0:o;99285:321::-;99414:15;;99402:9;:27;99398:202;;;96966:42;99445:56;99502:9;99513:13;99528:28;99545:5;99552:3;99528:16;:28::i;:::-;99566:4;99573:15;99445:144;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;99445:144:0;;;;;;;;;;;;:::i;100060:105::-;100119:7;100149:1;100145;:5;:13;;100157:1;100145:13;;;100153:1;100145:13;100138:20;100060:105;-1:-1:-1;;;100060:105:0:o;70592:628::-;70772:12;70800:7;70796:418;;;70827:10;:17;70848:1;70827:22;70823:286;;-1:-1:-1;;;;;64623:19:0;;;71034:60;;;;-1:-1:-1;;;71034:60:0;;14215:2:1;71034:60:0;;;14197:21:1;14254:2;14234:18;;;14227:30;14293:31;14273:18;;;14266:59;14342:18;;71034:60:0;14013:353:1;71034:60:0;-1:-1:-1;71129:10:0;71122:17;;70796:418;71170:33;71178:10;71190:12;71170:7;:33::i;95829:328::-;95967:49;;-1:-1:-1;;;95967:49:0;;95999:4;95967:49;;;14583:34:1;-1:-1:-1;;;;;14653:15:1;;;14633:18;;;14626:43;96019:7:0;;95967:23;;;;;;14518:18:1;;95967:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:59;95963:188;;;96042:39;-1:-1:-1;;;;;96042:25:0;;96068:9;96079:1;96042:25;:39::i;:::-;96095:45;-1:-1:-1;;;;;96095:25:0;;96121:9;96132:7;96095:25;:45::i;99612:442::-;99756:4;;99706:22;;-1:-1:-1;;;;;99756:4:0;;;;99740:13;;99784:17;;;;;:39;;;99818:5;-1:-1:-1;;;;;99805:18:0;:9;-1:-1:-1;;;;;99805:18:0;;99784:39;99770:53;;99855:6;:14;;99868:1;99855:14;;;99864:1;99855:14;99841:29;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;99841:29:0;;99833:37;;99891:8;99880:5;99886:1;99880:8;;;;;;;;:::i;:::-;;;;;;:19;-1:-1:-1;;;;;99880:19:0;;;-1:-1:-1;;;;;99880:19:0;;;;;99914:6;99910:138;;;99947:9;99936:5;99942:1;99936:8;;;;;;;;:::i;:::-;;;;;;:20;-1:-1:-1;;;;;99936:20:0;;;-1:-1:-1;;;;;99936:20:0;;;;;99910:138;;;99998:5;99987;99993:1;99987:8;;;;;;;;:::i;:::-;;;;;;:16;-1:-1:-1;;;;;99987:16:0;;;-1:-1:-1;;;;;99987:16:0;;;;;100028:9;100017:5;100023:1;100017:8;;;;;;;;:::i;:::-;;;;;;:20;-1:-1:-1;;;;;100017:20:0;;;-1:-1:-1;;;;;100017:20:0;;;;;99910:138;99730:324;;99612:442;;;;:::o;71742:540::-;71901:17;;:21;71897:379;;72129:10;72123:17;72185:15;72172:10;72168:2;72164:19;72157:44;71897:379;72252:12;72245:20;;-1:-1:-1;;;72245:20:0;;;;;;;;:::i;73861:573::-;74186:10;;;74185:62;;-1:-1:-1;74202:39:0;;-1:-1:-1;;;74202:39:0;;74226:4;74202:39;;;14583:34:1;-1:-1:-1;;;;;14653:15:1;;;14633:18;;;14626:43;74202:15:0;;;;;14518:18:1;;74202:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;74185:62;74164:163;;;;-1:-1:-1;;;74164:163:0;;15238:2:1;74164:163:0;;;15220:21:1;15277:2;15257:18;;;15250:30;15316:34;15296:18;;;15289:62;-1:-1:-1;;;15367:18:1;;;15360:52;15429:19;;74164:163:0;15036:418:1;74164:163:0;74364:62;;-1:-1:-1;;;;;5477:32:1;;74364:62:0;;;5459:51:1;5526:18;;;5519:34;;;74337:90:0;;74357:5;;-1:-1:-1;;;74387:22:0;5432:18:1;;74364:62:0;5285:274:1;196:173;264:20;;-1:-1:-1;;;;;313:31:1;;303:42;;293:70;;359:1;356;349:12;293:70;196:173;;;:::o;374:186::-;433:6;486:2;474:9;465:7;461:23;457:32;454:52;;;502:1;499;492:12;454:52;525:29;544:9;525:29;:::i;966:118::-;1052:5;1045:13;1038:21;1031:5;1028:32;1018:60;;1074:1;1071;1064:12;1089:161;1156:20;;1216:8;1205:20;;1195:31;;1185:59;;1240:1;1237;1230:12;1255:385;1327:6;1335;1343;1396:2;1384:9;1375:7;1371:23;1367:32;1364:52;;;1412:1;1409;1402:12;1364:52;1451:9;1438:23;1470:28;1492:5;1470:28;:::i;:::-;1517:5;-1:-1:-1;1541:37:1;1574:2;1559:18;;1541:37;:::i;:::-;1531:47;;1597:37;1630:2;1619:9;1615:18;1597:37;:::i;:::-;1587:47;;1255:385;;;;;:::o;1645:180::-;1704:6;1757:2;1745:9;1736:7;1732:23;1728:32;1725:52;;;1773:1;1770;1763:12;1725:52;-1:-1:-1;1796:23:1;;1645:180;-1:-1:-1;1645:180:1:o;2022:250::-;2107:1;2117:113;2131:6;2128:1;2125:13;2117:113;;;2207:11;;;2201:18;2188:11;;;2181:39;2153:2;2146:10;2117:113;;;-1:-1:-1;;2264:1:1;2246:16;;2239:27;2022:250::o;2277:270::-;2318:3;2356:5;2350:12;2383:6;2378:3;2371:19;2399:76;2468:6;2461:4;2456:3;2452:14;2445:4;2438:5;2434:16;2399:76;:::i;:::-;2529:2;2508:15;-1:-1:-1;;2504:29:1;2495:39;;;;2536:4;2491:50;;2277:270;-1:-1:-1;;2277:270:1:o;2552:298::-;2735:6;2728:14;2721:22;2710:9;2703:41;2780:2;2775;2764:9;2760:18;2753:30;2684:4;2800:44;2840:2;2829:9;2825:18;2817:6;2800:44;:::i;2855:272::-;2913:6;2966:2;2954:9;2945:7;2941:23;2937:32;2934:52;;;2982:1;2979;2972:12;2934:52;3021:9;3008:23;3071:6;3064:5;3060:18;3053:5;3050:29;3040:57;;3093:1;3090;3083:12;3132:241;3188:6;3241:2;3229:9;3220:7;3216:23;3212:32;3209:52;;;3257:1;3254;3247:12;3209:52;3296:9;3283:23;3315:28;3337:5;3315:28;:::i;3378:260::-;3446:6;3454;3507:2;3495:9;3486:7;3482:23;3478:32;3475:52;;;3523:1;3520;3513:12;3475:52;3546:29;3565:9;3546:29;:::i;:::-;3536:39;;3594:38;3628:2;3617:9;3613:18;3594:38;:::i;:::-;3584:48;;3378:260;;;;;:::o;3838:184::-;3908:6;3961:2;3949:9;3940:7;3936:23;3932:32;3929:52;;;3977:1;3974;3967:12;3929:52;-1:-1:-1;4000:16:1;;3838:184;-1:-1:-1;3838:184:1:o;4693:245::-;4760:6;4813:2;4801:9;4792:7;4788:23;4784:32;4781:52;;;4829:1;4826;4819:12;4781:52;4861:9;4855:16;4880:28;4902:5;4880:28;:::i;6193:127::-;6254:10;6249:3;6245:20;6242:1;6235:31;6285:4;6282:1;6275:15;6309:4;6306:1;6299:15;6325:125;6390:9;;;6411:10;;;6408:36;;;6424:18;;:::i;6455:168::-;6528:9;;;6559;;6576:15;;;6570:22;;6556:37;6546:71;;6597:18;;:::i;6628:217::-;6668:1;6694;6684:132;;6738:10;6733:3;6729:20;6726:1;6719:31;6773:4;6770:1;6763:15;6801:4;6798:1;6791:15;6684:132;-1:-1:-1;6830:9:1;;6628:217::o;6850:128::-;6917:9;;;6938:11;;;6935:37;;;6952:18;;:::i;8605:287::-;8734:3;8772:6;8766:13;8788:66;8847:6;8842:3;8835:4;8827:6;8823:17;8788:66;:::i;:::-;8870:16;;;;;8605:287;-1:-1:-1;;8605:287:1:o;11137:652::-;11334:2;11323:9;11316:21;11297:4;11372:6;11366:13;11415:4;11410:2;11399:9;11395:18;11388:32;11443:51;11489:3;11478:9;11474:19;11460:12;11443:51;:::i;:::-;11429:65;;11575:1;11571;11566:3;11562:11;11558:19;11552:2;11544:6;11540:15;11534:22;11530:48;11525:2;11514:9;11510:18;11503:76;11633:2;11625:6;11621:15;11615:22;11610:2;11599:9;11595:18;11588:50;11693:2;11685:6;11681:15;11675:22;11669:3;11658:9;11654:19;11647:51;11754:3;11746:6;11742:16;11736:23;11729:4;11718:9;11714:20;11707:53;11777:6;11769:14;;;11137:652;;;;:::o;11794:972::-;12048:4;12096:3;12085:9;12081:19;12127:6;12116:9;12109:25;12153:2;12191:6;12186:2;12175:9;12171:18;12164:34;12234:3;12229:2;12218:9;12214:18;12207:31;12258:6;12293;12287:13;12324:6;12316;12309:22;12362:3;12351:9;12347:19;12340:26;;12401:2;12393:6;12389:15;12375:29;;12422:1;12432:195;12446:6;12443:1;12440:13;12432:195;;;12511:13;;-1:-1:-1;;;;;12507:39:1;12495:52;;12602:15;;;;12567:12;;;;12543:1;12461:9;12432:195;;;-1:-1:-1;;;;;;;12683:32:1;;;;12678:2;12663:18;;12656:60;-1:-1:-1;;;12747:3:1;12732:19;12725:35;12644:3;11794:972;-1:-1:-1;;;11794:972:1:o;12771:127::-;12832:10;12827:3;12823:20;12820:1;12813:31;12863:4;12860:1;12853:15;12887:4;12884:1;12877:15;12903:1105;12998:6;13029:2;13072;13060:9;13051:7;13047:23;13043:32;13040:52;;;13088:1;13085;13078:12;13040:52;13121:9;13115:16;13150:18;13191:2;13183:6;13180:14;13177:34;;;13207:1;13204;13197:12;13177:34;13245:6;13234:9;13230:22;13220:32;;13290:7;13283:4;13279:2;13275:13;13271:27;13261:55;;13312:1;13309;13302:12;13261:55;13341:2;13335:9;13363:2;13359;13356:10;13353:36;;;13369:18;;:::i;:::-;13415:2;13412:1;13408:10;13447:2;13441:9;13510:2;13506:7;13501:2;13497;13493:11;13489:25;13481:6;13477:38;13565:6;13553:10;13550:22;13545:2;13533:10;13530:18;13527:46;13524:72;;;13576:18;;:::i;:::-;13612:2;13605:22;13662:18;;;13696:15;;;;-1:-1:-1;13738:11:1;;;13734:20;;;13766:19;;;13763:39;;;13798:1;13795;13788:12;13763:39;13822:11;;;;13842:135;13858:6;13853:3;13850:15;13842:135;;;13924:10;;13912:23;;13875:12;;;;13955;;;;13842:135;;;13996:6;12903:1105;-1:-1:-1;;;;;;;;12903:1105:1:o;14680:127::-;14741:10;14736:3;14732:20;14729:1;14722:31;14772:4;14769:1;14762:15;14796:4;14793:1;14786:15;14812:219;14961:2;14950:9;14943:21;14924:4;14981:44;15021:2;15010:9;15006:18;14998:6;14981:44;:::i
Swarm Source
ipfs://3457509467c4984d510102d6bae7ee98bfa314f1f9f8465165a465d6df9e0aa7
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.