Source Code
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 27 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Clone Router Str... | 17837328 | 964 days ago | IN | 0 ETH | 0.00808948 | ||||
| Clone Router Str... | 17837328 | 964 days ago | IN | 0 ETH | 0.00809274 | ||||
| Clone Router Str... | 17837328 | 964 days ago | IN | 0 ETH | 0.00809117 | ||||
| Clone Router Str... | 17837328 | 964 days ago | IN | 0 ETH | 0.00809117 | ||||
| Clone Router Str... | 17837263 | 964 days ago | IN | 0 ETH | 0.00807272 | ||||
| Clone Router Str... | 17837263 | 964 days ago | IN | 0 ETH | 0.00794819 | ||||
| Clone Router Str... | 17837263 | 964 days ago | IN | 0 ETH | 0.00807372 | ||||
| Clone Router Str... | 17837263 | 964 days ago | IN | 0 ETH | 0.00794842 | ||||
| Clone Router Str... | 17837263 | 964 days ago | IN | 0 ETH | 0.00794891 | ||||
| Clone Router Str... | 17837263 | 964 days ago | IN | 0 ETH | 0.00794908 | ||||
| Set Keeper | 17496595 | 1012 days ago | IN | 0 ETH | 0.0006582 | ||||
| Clone Router Str... | 17473597 | 1015 days ago | IN | 0 ETH | 0.00674113 | ||||
| Clone Router Str... | 17468093 | 1016 days ago | IN | 0 ETH | 0.00614258 | ||||
| Clone Router Str... | 17468090 | 1016 days ago | IN | 0 ETH | 0.00564304 | ||||
| Clone Router Str... | 17468086 | 1016 days ago | IN | 0 ETH | 0.00588609 | ||||
| Clone Router Str... | 17468068 | 1016 days ago | IN | 0 ETH | 0.00563494 | ||||
| Clone Router Str... | 17468062 | 1016 days ago | IN | 0 ETH | 0.00592426 | ||||
| Clone Router Str... | 17468061 | 1016 days ago | IN | 0 ETH | 0.00545744 | ||||
| Clone Router Str... | 17468053 | 1016 days ago | IN | 0 ETH | 0.00580434 | ||||
| Clone Router Str... | 17468053 | 1016 days ago | IN | 0 ETH | 0.00580434 | ||||
| Clone Router Str... | 17468053 | 1016 days ago | IN | 0 ETH | 0.00580451 | ||||
| Clone Router Str... | 17468053 | 1016 days ago | IN | 0 ETH | 0.00571709 | ||||
| Clone Router Str... | 17468053 | 1016 days ago | IN | 0 ETH | 0.00576395 | ||||
| Clone Router Str... | 17468048 | 1016 days ago | IN | 0 ETH | 0.00564248 | ||||
| Clone Router Str... | 17468048 | 1016 days ago | IN | 0 ETH | 0.00568219 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x3d602d80 | 17837328 | 964 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17837328 | 964 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17837328 | 964 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17837328 | 964 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17837263 | 964 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17837263 | 964 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17837263 | 964 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17837263 | 964 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17837263 | 964 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17837263 | 964 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17473597 | 1015 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17468093 | 1016 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17468090 | 1016 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17468086 | 1016 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17468068 | 1016 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17468062 | 1016 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17468061 | 1016 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17468053 | 1016 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17468053 | 1016 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17468053 | 1016 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17468053 | 1016 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17468053 | 1016 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17468048 | 1016 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17468048 | 1016 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17468048 | 1016 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
StrategyRouterV2
Compiler Version
v0.8.15+commit.e14f2714
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.15;
import "https://github.com/yearn/yearn-vaults/blob/v0.4.6/contracts/BaseStrategy.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
interface IVault is IERC20 {
function token() external view returns (address);
function decimals() external view returns (uint256);
function deposit() external;
function pricePerShare() external view returns (uint256);
function totalAssets() external view returns (uint256);
function lockedProfit() external view returns (uint256);
function lockedProfitDegradation() external view returns (uint256);
function lastReport() external view returns (uint256);
function withdraw(
uint256 amount,
address account,
uint256 maxLoss
) external returns (uint256);
}
interface IOracle {
// pull our asset price, in usdc, via yearn's oracle
function getPriceUsdcRecommended(address tokenAddress)
external
view
returns (uint256);
}
interface IHelper {
function sharesToAmount(address vault, uint256 shares)
external
view
returns (uint256);
function amountToShares(address vault, uint256 amount)
external
view
returns (uint256);
}
contract StrategyRouterV2 is BaseStrategy {
using SafeERC20 for IERC20;
/* ========== STATE VARIABLES ========== */
/// @notice The newer yVault we are routing this strategy to.
IVault public yVault;
/// @notice Max percentage loss we will take, in basis points (100% = 10_000). Default setting is zero.
uint256 public maxLoss;
/// @notice Address of our share value helper contract, which we use for conversions between shares and underlying amounts. Big 🧠 math here.
IHelper public constant shareValueHelper =
IHelper(0x444443bae5bB8640677A8cdF94CB8879Fec948Ec);
/// @notice Minimum profit size in USDC that we want to harvest.
/// @dev Only used in harvestTrigger.
uint256 public harvestProfitMinInUsdc;
/// @notice Maximum profit size in USDC that we want to harvest (ignore gas price once we get here).
/// @dev Only used in harvestTrigger.
uint256 public harvestProfitMaxInUsdc;
/// @notice Amount we accept as a loss in liquidatePosition if we don't get 100% back due to rounding errors.
uint256 public dustThreshold;
/// @notice Will only be true on the original deployed contract and not on clones; we don't want to clone a clone.
bool public isOriginal = true;
// Do I really need to explain this one?
string internal strategyName;
/* ========== CONSTRUCTOR ========== */
constructor(
address _vault,
address _yVault,
string memory _strategyName
) BaseStrategy(_vault) {
_initializeThis(_yVault, _strategyName);
}
/* ========== CLONING ========== */
event Cloned(address indexed clone);
/// @notice Use this to clone an exact copy of this strategy on another vault.
/// @param _vault Vault address we want to attach our new strategy to.
/// @param _strategist Address to grant the strategist role.
/// @param _rewards If we have any strategist rewards, send them here.
/// @param _keeper Address to grant the keeper role.
/// @param _yVault The newer vault we will route our funds to.
/// @param _strategyName Name to use for our new strategy.
function cloneRouterStrategy(
address _vault,
address _strategist,
address _rewards,
address _keeper,
address _yVault,
string memory _strategyName
) external virtual returns (address newStrategy) {
require(isOriginal);
// Copied from https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol
bytes20 addressBytes = bytes20(address(this));
assembly {
// EIP-1167 bytecode
let clone_code := mload(0x40)
mstore(
clone_code,
0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000
)
mstore(add(clone_code, 0x14), addressBytes)
mstore(
add(clone_code, 0x28),
0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000
)
newStrategy := create(0, clone_code, 0x37)
}
StrategyRouterV2(newStrategy).initialize(
_vault,
_strategist,
_rewards,
_keeper,
_yVault,
_strategyName
);
emit Cloned(newStrategy);
}
function initialize(
address _vault,
address _strategist,
address _rewards,
address _keeper,
address _yVault,
string memory _strategyName
) public {
require(address(yVault) == address(0));
_initialize(_vault, _strategist, _rewards, _keeper);
_initializeThis(_yVault, _strategyName);
}
function _initializeThis(address _yVault, string memory _strategyName)
internal
{
yVault = IVault(_yVault);
strategyName = _strategyName;
harvestProfitMinInUsdc = 5_000e6;
harvestProfitMaxInUsdc = 50_000e6;
dustThreshold = 10;
}
/* ========== VIEWS ========== */
/// @notice Strategy name.
function name() external view override returns (string memory) {
return strategyName;
}
/// @notice Total assets the strategy holds, sum of loose and staked want.
function estimatedTotalAssets()
public
view
virtual
override
returns (uint256)
{
return balanceOfWant() + valueOfInvestment();
}
/// @notice Assets delegated to another vault. Helps to avoid double-counting of TVL.
/// @dev While a strategy may have loose want, only donations would be unaccounted for, and thus are not counted here.
/// Note that a strategy could also have loose want from a manual withdrawFromYVault() call.
function delegatedAssets() public view override returns (uint256) {
return vault.strategies(address(this)).totalDebt;
}
/// @notice Balance of want sitting in our strategy.
function balanceOfWant() public view returns (uint256) {
return want.balanceOf(address(this));
}
/// @notice Balance of underlying we are holding as vault tokens of our delegated vault.
function valueOfInvestment() public view virtual returns (uint256) {
return
shareValueHelper.sharesToAmount(
address(yVault),
yVault.balanceOf(address(this))
);
}
/// @notice Balance of underlying we will gain on our next harvest
function claimableProfits() public view returns (uint256 profits) {
uint256 assets = estimatedTotalAssets();
uint256 debt = delegatedAssets();
if (assets > debt) {
unchecked {
profits = assets - debt;
}
} else {
profits = 0;
}
}
/* ========== CORE STRATEGY FUNCTIONS ========== */
function prepareReturn(uint256 _debtOutstanding)
internal
virtual
override
returns (
uint256 _profit,
uint256 _loss,
uint256 _debtPayment
)
{
// serious loss should never happen, but if it does, let's record it accurately
uint256 assets = estimatedTotalAssets();
uint256 debt = delegatedAssets();
// if assets are greater than debt, things are working great!
if (assets >= debt) {
unchecked {
_profit = assets - debt;
}
_debtPayment = _debtOutstanding;
uint256 toFree = _profit + _debtPayment;
// freed is math.min(wantBalance, toFree)
(uint256 freed, ) = liquidatePosition(toFree);
if (toFree > freed) {
if (_debtPayment >= freed) {
_debtPayment = freed;
_profit = 0;
} else {
unchecked {
_profit = freed - _debtPayment;
}
}
}
}
// if assets are less than debt, we are in trouble. don't worry about withdrawing here, just report losses
else {
unchecked {
_loss = debt - assets;
}
}
}
function adjustPosition(uint256 _debtOutstanding)
internal
virtual
override
{
if (emergencyExit) {
return;
}
uint256 balance = balanceOfWant();
if (balance > 0) {
_checkAllowance(address(yVault), address(want), balance);
yVault.deposit();
}
}
function liquidatePosition(uint256 _amountNeeded)
internal
virtual
override
returns (uint256 _liquidatedAmount, uint256 _loss)
{
uint256 balance = balanceOfWant();
if (balance >= _amountNeeded) {
return (_amountNeeded, 0);
}
uint256 toWithdraw;
unchecked {
toWithdraw = _amountNeeded - balance;
}
// withdraw the remainder we need
_withdrawFromYVault(toWithdraw);
uint256 looseWant = balanceOfWant();
// because of slippage, dust-sized losses are acceptable
// however, we don't want to take losses for funds stuck in a strategy in the destination vault
if (_amountNeeded > looseWant) {
uint256 diff = _amountNeeded - looseWant;
_liquidatedAmount = looseWant;
if (diff < dustThreshold) {
_loss = diff;
}
} else {
_liquidatedAmount = _amountNeeded;
}
}
/// @notice Manually withdraw underlying assets from our target vault.
/// @dev Only governance or management may call this.
/// @param _amount Shares of our target vault to withdraw.
function withdrawFromYVault(uint256 _amount) external onlyVaultManagers {
_withdrawFromYVault(_amount);
}
function _withdrawFromYVault(uint256 _amount) internal {
if (_amount == 0) {
return;
}
uint256 _balanceOfYShares = yVault.balanceOf(address(this));
uint256 sharesToWithdraw =
Math.min(
shareValueHelper.amountToShares(address(yVault), _amount),
_balanceOfYShares
);
if (sharesToWithdraw == 0) {
return;
}
yVault.withdraw(sharesToWithdraw, address(this), maxLoss);
}
function liquidateAllPositions()
internal
virtual
override
returns (uint256 _amountFreed)
{
// withdraw as much as we can from vault tokens
uint256 vaultTokenBalance = yVault.balanceOf(address(this));
if (vaultTokenBalance > 0) {
yVault.withdraw(vaultTokenBalance, address(this), maxLoss);
}
// return our want balance
return balanceOfWant();
}
function prepareMigration(address _newStrategy) internal virtual override {
IERC20(yVault).safeTransfer(
_newStrategy,
IERC20(yVault).balanceOf(address(this))
);
}
function protectedTokens()
internal
view
override
returns (address[] memory ret)
{}
function _checkAllowance(
address _contract,
address _token,
uint256 _amount
) internal {
if (IERC20(_token).allowance(address(this), _contract) < _amount) {
IERC20(_token).safeApprove(_contract, 0);
IERC20(_token).safeApprove(_contract, type(uint256).max);
}
}
/// @notice Convert our keeper's eth cost into want
/// @dev We don't use this since we don't factor call cost into our harvestTrigger.
/// @param _amtInWei Amount of ether spent.
/// @return Value of ether in want.
function ethToWant(uint256 _amtInWei)
public
view
virtual
override
returns (uint256)
{}
/* ========== KEEP3RS ========== */
/**
* @notice
* Provide a signal to the keeper that harvest() should be called.
*
* Don't harvest if a strategy is inactive.
* If our profit exceeds our upper limit, then harvest no matter what. For
* our lower profit limit, credit threshold, max delay, and manual force trigger,
* only harvest if our gas price is acceptable.
*
* @param callCostinEth The keeper's estimated gas cost to call harvest() (in wei).
* @return True if harvest() should be called, false otherwise.
*/
function harvestTrigger(uint256 callCostinEth)
public
view
override
returns (bool)
{
// Should not trigger if strategy is not active (no assets and no debtRatio). This means we don't need to adjust keeper job.
if (!isActive()) {
return false;
}
// harvest if we have a profit to claim at our upper limit without considering gas price
uint256 claimableProfit = claimableProfitInUsdc();
if (claimableProfit > harvestProfitMaxInUsdc) {
return true;
}
// check if the base fee gas price is higher than we allow. if it is, block harvests.
if (!isBaseFeeAcceptable()) {
return false;
}
// trigger if we want to manually harvest, but only if our gas price is acceptable
if (forceHarvestTriggerOnce) {
return true;
}
// harvest if we have a sufficient profit to claim, but only if our gas price is acceptable
if (claimableProfit > harvestProfitMinInUsdc) {
return true;
}
StrategyParams memory params = vault.strategies(address(this));
// harvest regardless of profit once we reach our maxDelay
if (block.timestamp - params.lastReport > maxReportDelay) {
return true;
}
// harvest our credit if it's above our threshold
if (vault.creditAvailable() > creditThreshold) {
return true;
}
// otherwise, we don't harvest
return false;
}
/// @notice Calculates the profit if all claimable assets were sold for USDC (6 decimals).
/// @dev Uses yearn's lens oracle, if returned values are strange then troubleshoot there.
/// @return Total return in USDC from taking profits on yToken gains.
function claimableProfitInUsdc() public view returns (uint256) {
IOracle yearnOracle =
IOracle(0x83d95e0D5f402511dB06817Aff3f9eA88224B030); // yearn lens oracle
uint256 underlyingPrice =
yearnOracle.getPriceUsdcRecommended(address(want));
// Oracle returns prices as 6 decimals, so multiply by claimable amount and divide by token decimals
return (claimableProfits() * underlyingPrice) / (10**yVault.decimals());
}
/* ========== SETTERS ========== */
// These functions are useful for setting parameters of the strategy that may need to be adjusted.
/// @notice Set the maximum loss we will accept (due to slippage or locked funds) on a vault withdrawal.
/// @dev Generally, this should be zero, and this function will only be used in special/emergency cases.
/// @param _maxLoss Max percentage loss we will take, in basis points (100% = 10_000).
function setMaxLoss(uint256 _maxLoss) public onlyVaultManagers {
maxLoss = _maxLoss;
}
/// @notice This allows us to set the dust threshold for our strategy.
/// @param _dustThreshold This sets what dust is. If we have less than this remaining after withdrawing, accept it as a loss.
function setDustThreshold(uint256 _dustThreshold)
external
onlyVaultManagers
{
require(_dustThreshold < 10000, "Your size is too much size");
dustThreshold = _dustThreshold;
}
/**
* @notice
* Here we set various parameters to optimize our harvestTrigger.
* @param _harvestProfitMinInUsdc The amount of profit (in USDC, 6 decimals)
* that will trigger a harvest if gas price is acceptable.
* @param _harvestProfitMaxInUsdc The amount of profit in USDC that
* will trigger a harvest regardless of gas price.
*/
function setHarvestTriggerParams(
uint256 _harvestProfitMinInUsdc,
uint256 _harvestProfitMaxInUsdc
) external onlyVaultManagers {
harvestProfitMinInUsdc = _harvestProfitMinInUsdc;
harvestProfitMaxInUsdc = _harvestProfitMaxInUsdc;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.15;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
struct StrategyParams {
uint256 performanceFee;
uint256 activation;
uint256 debtRatio;
uint256 minDebtPerHarvest;
uint256 maxDebtPerHarvest;
uint256 lastReport;
uint256 totalDebt;
uint256 totalGain;
uint256 totalLoss;
}
interface VaultAPI is IERC20 {
function name() external view returns (string calldata);
function symbol() external view returns (string calldata);
function decimals() external view returns (uint256);
function apiVersion() external pure returns (string memory);
function permit(
address owner,
address spender,
uint256 amount,
uint256 expiry,
bytes calldata signature
) external returns (bool);
// NOTE: Vyper produces multiple signatures for a given function with "default" args
function deposit() external returns (uint256);
function deposit(uint256 amount) external returns (uint256);
function deposit(uint256 amount, address recipient) external returns (uint256);
// NOTE: Vyper produces multiple signatures for a given function with "default" args
function withdraw() external returns (uint256);
function withdraw(uint256 maxShares) external returns (uint256);
function withdraw(uint256 maxShares, address recipient) external returns (uint256);
function token() external view returns (address);
function strategies(address _strategy) external view returns (StrategyParams memory);
function pricePerShare() external view returns (uint256);
function totalAssets() external view returns (uint256);
function depositLimit() external view returns (uint256);
function maxAvailableShares() external view returns (uint256);
/**
* View how much the Vault would increase this Strategy's borrow limit,
* based on its present performance (since its last report). Can be used to
* determine expectedReturn in your Strategy.
*/
function creditAvailable() external view returns (uint256);
/**
* View how much the Vault would like to pull back from the Strategy,
* based on its present performance (since its last report). Can be used to
* determine expectedReturn in your Strategy.
*/
function debtOutstanding() external view returns (uint256);
/**
* View how much the Vault expect this Strategy to return at the current
* block, based on its present performance (since its last report). Can be
* used to determine expectedReturn in your Strategy.
*/
function expectedReturn() external view returns (uint256);
/**
* This is the main contact point where the Strategy interacts with the
* Vault. It is critical that this call is handled as intended by the
* Strategy. Therefore, this function will be called by BaseStrategy to
* make sure the integration is correct.
*/
function report(
uint256 _gain,
uint256 _loss,
uint256 _debtPayment
) external returns (uint256);
/**
* This function should only be used in the scenario where the Strategy is
* being retired but no migration of the positions are possible, or in the
* extreme scenario that the Strategy needs to be put into "Emergency Exit"
* mode in order for it to exit as quickly as possible. The latter scenario
* could be for any reason that is considered "critical" that the Strategy
* exits its position as fast as possible, such as a sudden change in
* market conditions leading to losses, or an imminent failure in an
* external dependency.
*/
function revokeStrategy() external;
/**
* View the governance address of the Vault to assert privileged functions
* can only be called by governance. The Strategy serves the Vault, so it
* is subject to governance defined by the Vault.
*/
function governance() external view returns (address);
/**
* View the management address of the Vault to assert privileged functions
* can only be called by management. The Strategy serves the Vault, so it
* is subject to management defined by the Vault.
*/
function management() external view returns (address);
/**
* View the guardian address of the Vault to assert privileged functions
* can only be called by guardian. The Strategy serves the Vault, so it
* is subject to guardian defined by the Vault.
*/
function guardian() external view returns (address);
}
/**
* This interface is here for the keeper bot to use.
*/
interface StrategyAPI {
function name() external view returns (string memory);
function vault() external view returns (address);
function want() external view returns (address);
function apiVersion() external pure returns (string memory);
function keeper() external view returns (address);
function isActive() external view returns (bool);
function delegatedAssets() external view returns (uint256);
function estimatedTotalAssets() external view returns (uint256);
function tendTrigger(uint256 callCost) external view returns (bool);
function tend() external;
function harvestTrigger(uint256 callCost) external view returns (bool);
function harvest() external;
event Harvested(uint256 profit, uint256 loss, uint256 debtPayment, uint256 debtOutstanding);
}
interface HealthCheck {
function check(
uint256 profit,
uint256 loss,
uint256 debtPayment,
uint256 debtOutstanding,
uint256 totalDebt
) external view returns (bool);
}
interface IBaseFee {
function isCurrentBaseFeeAcceptable() external view returns (bool);
}
/**
* @title Yearn Base Strategy
* @author yearn.finance
* @notice
* BaseStrategy implements all of the required functionality to interoperate
* closely with the Vault contract. This contract should be inherited and the
* abstract methods implemented to adapt the Strategy to the particular needs
* it has to create a return.
*
* Of special interest is the relationship between `harvest()` and
* `vault.report()'. `harvest()` may be called simply because enough time has
* elapsed since the last report, and not because any funds need to be moved
* or positions adjusted. This is critical so that the Vault may maintain an
* accurate picture of the Strategy's performance. See `vault.report()`,
* `harvest()`, and `harvestTrigger()` for further details.
*/
abstract contract BaseStrategy {
using SafeERC20 for IERC20;
string public metadataURI;
// health checks
bool public doHealthCheck;
address public healthCheck;
/**
* @notice
* Used to track which version of `StrategyAPI` this Strategy
* implements.
* @dev The Strategy's version must match the Vault's `API_VERSION`.
* @return A string which holds the current API version of this contract.
*/
function apiVersion() public pure returns (string memory) {
return "0.4.6";
}
/**
* @notice This Strategy's name.
* @dev
* You can use this field to manage the "version" of this Strategy, e.g.
* `StrategySomethingOrOtherV1`. However, "API Version" is managed by
* `apiVersion()` function above.
* @return This Strategy's name.
*/
function name() external view virtual returns (string memory);
/**
* @notice
* The amount (priced in want) of the total assets managed by this strategy should not count
* towards Yearn's TVL calculations.
* @dev
* You can override this field to set it to a non-zero value if some of the assets of this
* Strategy is somehow delegated inside another part of of Yearn's ecosystem e.g. another Vault.
* Note that this value must be strictly less than or equal to the amount provided by
* `estimatedTotalAssets()` below, as the TVL calc will be total assets minus delegated assets.
* Also note that this value is used to determine the total assets under management by this
* strategy, for the purposes of computing the management fee in `Vault`
* @return
* The amount of assets this strategy manages that should not be included in Yearn's Total Value
* Locked (TVL) calculation across it's ecosystem.
*/
function delegatedAssets() external view virtual returns (uint256) {
return 0;
}
VaultAPI public vault;
address public strategist;
address public rewards;
address public keeper;
IERC20 public want;
// So indexers can keep track of this
event Harvested(uint256 profit, uint256 loss, uint256 debtPayment, uint256 debtOutstanding);
event UpdatedStrategist(address newStrategist);
event UpdatedKeeper(address newKeeper);
event UpdatedRewards(address rewards);
event UpdatedMinReportDelay(uint256 delay);
event UpdatedMaxReportDelay(uint256 delay);
event UpdatedBaseFeeOracle(address baseFeeOracle);
event UpdatedCreditThreshold(uint256 creditThreshold);
event ForcedHarvestTrigger(bool triggerState);
event EmergencyExitEnabled();
event UpdatedMetadataURI(string metadataURI);
event SetHealthCheck(address);
event SetDoHealthCheck(bool);
// The minimum number of seconds between harvest calls. See
// `setMinReportDelay()` for more details.
uint256 public minReportDelay;
// The maximum number of seconds between harvest calls. See
// `setMaxReportDelay()` for more details.
uint256 public maxReportDelay;
// See note on `setEmergencyExit()`.
bool public emergencyExit;
// See note on `isBaseFeeOracleAcceptable()`.
address public baseFeeOracle;
// See note on `setCreditThreshold()`
uint256 public creditThreshold;
// See note on `setForceHarvestTriggerOnce`
bool public forceHarvestTriggerOnce;
// modifiers
modifier onlyAuthorized() {
_onlyAuthorized();
_;
}
modifier onlyEmergencyAuthorized() {
_onlyEmergencyAuthorized();
_;
}
modifier onlyStrategist() {
_onlyStrategist();
_;
}
modifier onlyGovernance() {
_onlyGovernance();
_;
}
modifier onlyRewarder() {
_onlyRewarder();
_;
}
modifier onlyKeepers() {
_onlyKeepers();
_;
}
modifier onlyVaultManagers() {
_onlyVaultManagers();
_;
}
function _onlyAuthorized() internal {
require(msg.sender == strategist || msg.sender == governance());
}
function _onlyEmergencyAuthorized() internal {
require(msg.sender == strategist || msg.sender == governance() || msg.sender == vault.guardian() || msg.sender == vault.management());
}
function _onlyStrategist() internal {
require(msg.sender == strategist);
}
function _onlyGovernance() internal {
require(msg.sender == governance());
}
function _onlyRewarder() internal {
require(msg.sender == governance() || msg.sender == strategist);
}
function _onlyKeepers() internal {
require(
msg.sender == keeper ||
msg.sender == strategist ||
msg.sender == governance() ||
msg.sender == vault.guardian() ||
msg.sender == vault.management()
);
}
function _onlyVaultManagers() internal {
require(msg.sender == vault.management() || msg.sender == governance());
}
constructor(address _vault) {
_initialize(_vault, msg.sender, msg.sender, msg.sender);
}
/**
* @notice
* Initializes the Strategy, this is called only once, when the
* contract is deployed.
* @dev `_vault` should implement `VaultAPI`.
* @param _vault The address of the Vault responsible for this Strategy.
* @param _strategist The address to assign as `strategist`.
* The strategist is able to change the reward address
* @param _rewards The address to use for pulling rewards.
* @param _keeper The adddress of the _keeper. _keeper
* can harvest and tend a strategy.
*/
function _initialize(
address _vault,
address _strategist,
address _rewards,
address _keeper
) internal {
require(address(want) == address(0), "Strategy already initialized");
vault = VaultAPI(_vault);
want = IERC20(vault.token());
want.safeApprove(_vault, type(uint256).max); // Give Vault unlimited access (might save gas)
strategist = _strategist;
rewards = _rewards;
keeper = _keeper;
// initialize variables
maxReportDelay = 30 days;
creditThreshold = 1_000_000 * 10**vault.decimals(); // set this high by default so we don't get tons of false triggers if not changed
vault.approve(rewards, type(uint256).max); // Allow rewards to be pulled
}
function setHealthCheck(address _healthCheck) external onlyVaultManagers {
emit SetHealthCheck(_healthCheck);
healthCheck = _healthCheck;
}
function setDoHealthCheck(bool _doHealthCheck) external onlyVaultManagers {
emit SetDoHealthCheck(_doHealthCheck);
doHealthCheck = _doHealthCheck;
}
/**
* @notice
* Used to change `strategist`.
*
* This may only be called by governance or the existing strategist.
* @param _strategist The new address to assign as `strategist`.
*/
function setStrategist(address _strategist) external onlyAuthorized {
require(_strategist != address(0));
strategist = _strategist;
emit UpdatedStrategist(_strategist);
}
/**
* @notice
* Used to change `keeper`.
*
* `keeper` is the only address that may call `tend()` or `harvest()`,
* other than `governance()` or `strategist`. However, unlike
* `governance()` or `strategist`, `keeper` may *only* call `tend()`
* and `harvest()`, and no other authorized functions, following the
* principle of least privilege.
*
* This may only be called by governance or the strategist.
* @param _keeper The new address to assign as `keeper`.
*/
function setKeeper(address _keeper) external onlyAuthorized {
require(_keeper != address(0));
keeper = _keeper;
emit UpdatedKeeper(_keeper);
}
/**
* @notice
* Used to change `rewards`. EOA or smart contract which has the permission
* to pull rewards from the vault.
*
* This may only be called by the strategist.
* @param _rewards The address to use for pulling rewards.
*/
function setRewards(address _rewards) external onlyRewarder {
require(_rewards != address(0));
vault.approve(rewards, 0);
rewards = _rewards;
vault.approve(rewards, type(uint256).max);
emit UpdatedRewards(_rewards);
}
/**
* @notice
* Used to change `minReportDelay`. `minReportDelay` is the minimum number
* of blocks that should pass for `harvest()` to be called.
*
* For external keepers (such as the Keep3r network), this is the minimum
* time between jobs to wait. (see `harvestTrigger()`
* for more details.)
*
* This may only be called by governance or the strategist.
* @param _delay The minimum number of seconds to wait between harvests.
*/
function setMinReportDelay(uint256 _delay) external onlyAuthorized {
minReportDelay = _delay;
emit UpdatedMinReportDelay(_delay);
}
/**
* @notice
* Used to change `maxReportDelay`. `maxReportDelay` is the maximum number
* of blocks that should pass for `harvest()` to be called.
*
* For external keepers (such as the Keep3r network), this is the maximum
* time between jobs to wait. (see `harvestTrigger()`
* for more details.)
*
* This may only be called by governance or the strategist.
* @param _delay The maximum number of seconds to wait between harvests.
*/
function setMaxReportDelay(uint256 _delay) external onlyAuthorized {
maxReportDelay = _delay;
emit UpdatedMaxReportDelay(_delay);
}
/**
* @notice
* Used to ensure that any significant credit a strategy has from the
* vault will be automatically harvested.
*
* This may only be called by governance or management.
* @param _creditThreshold The number of want tokens that will
* automatically trigger a harvest.
*/
function setCreditThreshold(uint256 _creditThreshold) external onlyVaultManagers {
creditThreshold = _creditThreshold;
emit UpdatedCreditThreshold(_creditThreshold);
}
/**
* @notice
* Used to automatically trigger a harvest by our keepers. Can be
* useful if gas prices are too high now, and we want to harvest
* later once prices have lowered.
*
* This may only be called by governance or management.
* @param _forceHarvestTriggerOnce Value of true tells keepers to harvest
* our strategy
*/
function setForceHarvestTriggerOnce(bool _forceHarvestTriggerOnce) external onlyVaultManagers {
forceHarvestTriggerOnce = _forceHarvestTriggerOnce;
emit ForcedHarvestTrigger(_forceHarvestTriggerOnce);
}
/**
* @notice
* Used to set our baseFeeOracle, which checks the network's current base
* fee price to determine whether it is an optimal time to harvest or tend.
*
* This may only be called by governance or management.
* @param _baseFeeOracle Address of our baseFeeOracle
*/
function setBaseFeeOracle(address _baseFeeOracle) external onlyVaultManagers {
baseFeeOracle = _baseFeeOracle;
emit UpdatedBaseFeeOracle(_baseFeeOracle);
}
/**
* @notice
* Used to change `metadataURI`. `metadataURI` is used to store the URI
* of the file describing the strategy.
*
* This may only be called by governance or the strategist.
* @param _metadataURI The URI that describe the strategy.
*/
function setMetadataURI(string calldata _metadataURI) external onlyAuthorized {
metadataURI = _metadataURI;
emit UpdatedMetadataURI(_metadataURI);
}
/**
* Resolve governance address from Vault contract, used to make assertions
* on protected functions in the Strategy.
*/
function governance() internal view returns (address) {
return vault.governance();
}
/**
* @notice
* Provide an accurate conversion from `_amtInWei` (denominated in wei)
* to `want` (using the native decimal characteristics of `want`).
* @dev
* Care must be taken when working with decimals to assure that the conversion
* is compatible. As an example:
*
* given 1e17 wei (0.1 ETH) as input, and want is USDC (6 decimals),
* with USDC/ETH = 1800, this should give back 1800000000 (180 USDC)
*
* @param _amtInWei The amount (in wei/1e-18 ETH) to convert to `want`
* @return The amount in `want` of `_amtInEth` converted to `want`
**/
function ethToWant(uint256 _amtInWei) public view virtual returns (uint256);
/**
* @notice
* Provide an accurate estimate for the total amount of assets
* (principle + return) that this Strategy is currently managing,
* denominated in terms of `want` tokens.
*
* This total should be "realizable" e.g. the total value that could
* *actually* be obtained from this Strategy if it were to divest its
* entire position based on current on-chain conditions.
* @dev
* Care must be taken in using this function, since it relies on external
* systems, which could be manipulated by the attacker to give an inflated
* (or reduced) value produced by this function, based on current on-chain
* conditions (e.g. this function is possible to influence through
* flashloan attacks, oracle manipulations, or other DeFi attack
* mechanisms).
*
* It is up to governance to use this function to correctly order this
* Strategy relative to its peers in the withdrawal queue to minimize
* losses for the Vault based on sudden withdrawals. This value should be
* higher than the total debt of the Strategy and higher than its expected
* value to be "safe".
* @return The estimated total assets in this Strategy.
*/
function estimatedTotalAssets() public view virtual returns (uint256);
/*
* @notice
* Provide an indication of whether this strategy is currently "active"
* in that it is managing an active position, or will manage a position in
* the future. This should correlate to `harvest()` activity, so that Harvest
* events can be tracked externally by indexing agents.
* @return True if the strategy is actively managing a position.
*/
function isActive() public view returns (bool) {
return vault.strategies(address(this)).debtRatio > 0 || estimatedTotalAssets() > 0;
}
/**
* Perform any Strategy unwinding or other calls necessary to capture the
* "free return" this Strategy has generated since the last time its core
* position(s) were adjusted. Examples include unwrapping extra rewards.
* This call is only used during "normal operation" of a Strategy, and
* should be optimized to minimize losses as much as possible.
*
* This method returns any realized profits and/or realized losses
* incurred, and should return the total amounts of profits/losses/debt
* payments (in `want` tokens) for the Vault's accounting (e.g.
* `want.balanceOf(this) >= _debtPayment + _profit`).
*
* `_debtOutstanding` will be 0 if the Strategy is not past the configured
* debt limit, otherwise its value will be how far past the debt limit
* the Strategy is. The Strategy's debt limit is configured in the Vault.
*
* NOTE: `_debtPayment` should be less than or equal to `_debtOutstanding`.
* It is okay for it to be less than `_debtOutstanding`, as that
* should only used as a guide for how much is left to pay back.
* Payments should be made to minimize loss from slippage, debt,
* withdrawal fees, etc.
*
* See `vault.debtOutstanding()`.
*/
function prepareReturn(uint256 _debtOutstanding)
internal
virtual
returns (
uint256 _profit,
uint256 _loss,
uint256 _debtPayment
);
/**
* Perform any adjustments to the core position(s) of this Strategy given
* what change the Vault made in the "investable capital" available to the
* Strategy. Note that all "free capital" in the Strategy after the report
* was made is available for reinvestment. Also note that this number
* could be 0, and you should handle that scenario accordingly.
*
* See comments regarding `_debtOutstanding` on `prepareReturn()`.
*/
function adjustPosition(uint256 _debtOutstanding) internal virtual;
/**
* Liquidate up to `_amountNeeded` of `want` of this strategy's positions,
* irregardless of slippage. Any excess will be re-invested with `adjustPosition()`.
* This function should return the amount of `want` tokens made available by the
* liquidation. If there is a difference between them, `_loss` indicates whether the
* difference is due to a realized loss, or if there is some other sitution at play
* (e.g. locked funds) where the amount made available is less than what is needed.
*
* NOTE: The invariant `_liquidatedAmount + _loss <= _amountNeeded` should always be maintained
*/
function liquidatePosition(uint256 _amountNeeded) internal virtual returns (uint256 _liquidatedAmount, uint256 _loss);
/**
* Liquidate everything and returns the amount that got freed.
* This function is used during emergency exit instead of `prepareReturn()` to
* liquidate all of the Strategy's positions back to the Vault.
*/
function liquidateAllPositions() internal virtual returns (uint256 _amountFreed);
/**
* @notice
* Provide a signal to the keeper that `tend()` should be called. The
* keeper will provide the estimated gas cost that they would pay to call
* `tend()`, and this function should use that estimate to make a
* determination if calling it is "worth it" for the keeper. This is not
* the only consideration into issuing this trigger, for example if the
* position would be negatively affected if `tend()` is not called
* shortly, then this can return `true` even if the keeper might be
* "at a loss" (keepers are always reimbursed by Yearn).
* @dev
* `callCostInWei` must be priced in terms of `wei` (1e-18 ETH).
*
* This call and `harvestTrigger()` should never return `true` at the same
* time.
* @param callCostInWei The keeper's estimated gas cost to call `tend()` (in wei).
* @return `true` if `tend()` should be called, `false` otherwise.
*/
function tendTrigger(uint256 callCostInWei) public view virtual returns (bool) {
// We usually don't need tend, but if there are positions that need
// active maintainence, overriding this function is how you would
// signal for that.
// If your implementation uses the cost of the call in want, you can
// use uint256 callCost = ethToWant(callCostInWei);
// It is highly suggested to use the baseFeeOracle here as well.
return false;
}
/**
* @notice
* Adjust the Strategy's position. The purpose of tending isn't to
* realize gains, but to maximize yield by reinvesting any returns.
*
* See comments on `adjustPosition()`.
*
* This may only be called by governance, the strategist, or the keeper.
*/
function tend() external onlyKeepers {
// Don't take profits with this call, but adjust for better gains
adjustPosition(vault.debtOutstanding());
}
/**
* @notice
* Provide a signal to the keeper that `harvest()` should be called. The
* keeper will provide the estimated gas cost that they would pay to call
* `harvest()`, and this function should use that estimate to make a
* determination if calling it is "worth it" for the keeper. This is not
* the only consideration into issuing this trigger, for example if the
* position would be negatively affected if `harvest()` is not called
* shortly, then this can return `true` even if the keeper might be "at a
* loss" (keepers are always reimbursed by Yearn).
* @dev
* `callCostInWei` must be priced in terms of `wei` (1e-18 ETH).
*
* This call and `tendTrigger` should never return `true` at the
* same time.
*
* See `maxReportDelay`, `creditThreshold` to adjust the
* strategist-controlled parameters that will influence whether this call
* returns `true` or not. These parameters will be used in conjunction
* with the parameters reported to the Vault (see `params`) to determine
* if calling `harvest()` is merited.
*
* This trigger also checks the network's base fee to avoid harvesting during
* times of high network congestion.
*
* Consider use of super.harvestTrigger() in any override to build on top
* of this logic instead of replacing it. For example, if using `minReportDelay`.
*
* It is expected that an external system will check `harvestTrigger()`.
* This could be a script run off a desktop or cloud bot (e.g.
* https://github.com/iearn-finance/yearn-vaults/blob/main/scripts/keep.py),
* or via an integration with the Keep3r network (e.g.
* https://github.com/Macarse/GenericKeep3rV2/blob/master/contracts/keep3r/GenericKeep3rV2.sol).
* @param callCostInWei The keeper's estimated gas cost to call `harvest()` (in wei).
* @return `true` if `harvest()` should be called, `false` otherwise.
*/
function harvestTrigger(uint256 callCostInWei) public view virtual returns (bool) {
// Should not trigger if strategy is not active (no assets or no debtRatio)
if (!isActive()) return false;
// check if the base fee gas price is higher than we allow. if it is, block harvests.
if (!isBaseFeeAcceptable()) return false;
// trigger if we want to manually harvest, but only if our gas price is acceptable
if (forceHarvestTriggerOnce) return true;
// Should trigger if hasn't been called in a while
StrategyParams memory params = vault.strategies(address(this));
if ((block.timestamp - params.lastReport) >= maxReportDelay) return true;
// harvest our credit if it's above our threshold or return false
return (vault.creditAvailable() > creditThreshold);
}
/**
* @notice
* Check if the current network base fee is below our external target. If
* not, then harvestTrigger will return false.
* @return `true` if `harvest()` should be allowed, `false` otherwise.
*/
function isBaseFeeAcceptable() public view returns (bool) {
if (baseFeeOracle == address(0)) return true;
else return IBaseFee(baseFeeOracle).isCurrentBaseFeeAcceptable();
}
/**
* @notice
* Harvests the Strategy, recognizing any profits or losses and adjusting
* the Strategy's position.
*
* In the rare case the Strategy is in emergency shutdown, this will exit
* the Strategy's position.
*
* This may only be called by governance, the strategist, or the keeper.
* @dev
* When `harvest()` is called, the Strategy reports to the Vault (via
* `vault.report()`), so in some cases `harvest()` must be called in order
* to take in profits, to borrow newly available funds from the Vault, or
* otherwise adjust its position. In other cases `harvest()` must be
* called to report to the Vault on the Strategy's position, especially if
* any losses have occurred.
*/
function harvest() external onlyKeepers {
uint256 profit = 0;
uint256 loss = 0;
uint256 debtOutstanding = vault.debtOutstanding();
uint256 debtPayment = 0;
if (emergencyExit) {
// Free up as much capital as possible
uint256 amountFreed = liquidateAllPositions();
if (amountFreed < debtOutstanding) {
loss = debtOutstanding - amountFreed;
} else if (amountFreed > debtOutstanding) {
profit = amountFreed - debtOutstanding;
}
debtPayment = debtOutstanding - loss;
} else {
// Free up returns for Vault to pull
(profit, loss, debtPayment) = prepareReturn(debtOutstanding);
}
// we're done harvesting, so reset our trigger if we used it
forceHarvestTriggerOnce = false;
emit ForcedHarvestTrigger(false);
// Allow Vault to take up to the "harvested" balance of this contract,
// which is the amount it has earned since the last time it reported to
// the Vault.
uint256 totalDebt = vault.strategies(address(this)).totalDebt;
debtOutstanding = vault.report(profit, loss, debtPayment);
// Check if free returns are left, and re-invest them
adjustPosition(debtOutstanding);
// call healthCheck contract
if (doHealthCheck && healthCheck != address(0)) {
require(HealthCheck(healthCheck).check(profit, loss, debtPayment, debtOutstanding, totalDebt), "!healthcheck");
} else {
emit SetDoHealthCheck(true);
doHealthCheck = true;
}
emit Harvested(profit, loss, debtPayment, debtOutstanding);
}
/**
* @notice
* Withdraws `_amountNeeded` to `vault`.
*
* This may only be called by the Vault.
* @param _amountNeeded How much `want` to withdraw.
* @return _loss Any realized losses
*/
function withdraw(uint256 _amountNeeded) external returns (uint256 _loss) {
require(msg.sender == address(vault), "!vault");
// Liquidate as much as possible to `want`, up to `_amountNeeded`
uint256 amountFreed;
(amountFreed, _loss) = liquidatePosition(_amountNeeded);
// Send it directly back (NOTE: Using `msg.sender` saves some gas here)
want.safeTransfer(msg.sender, amountFreed);
// NOTE: Reinvest anything leftover on next `tend`/`harvest`
}
/**
* Do anything necessary to prepare this Strategy for migration, such as
* transferring any reserve or LP tokens, CDPs, or other tokens or stores of
* value.
*/
function prepareMigration(address _newStrategy) internal virtual;
/**
* @notice
* Transfers all `want` from this Strategy to `_newStrategy`.
*
* This may only be called by the Vault.
* @dev
* The new Strategy's Vault must be the same as this Strategy's Vault.
* The migration process should be carefully performed to make sure all
* the assets are migrated to the new address, which should have never
* interacted with the vault before.
* @param _newStrategy The Strategy to migrate to.
*/
function migrate(address _newStrategy) external {
require(msg.sender == address(vault));
require(BaseStrategy(_newStrategy).vault() == vault);
prepareMigration(_newStrategy);
want.safeTransfer(_newStrategy, want.balanceOf(address(this)));
}
/**
* @notice
* Activates emergency exit. Once activated, the Strategy will exit its
* position upon the next harvest, depositing all funds into the Vault as
* quickly as is reasonable given on-chain conditions.
*
* This may only be called by governance or the strategist.
* @dev
* See `vault.setEmergencyShutdown()` and `harvest()` for further details.
*/
function setEmergencyExit() external onlyEmergencyAuthorized {
emergencyExit = true;
if (vault.strategies(address(this)).debtRatio != 0) {
vault.revokeStrategy();
}
emit EmergencyExitEnabled();
}
/**
* Override this to add all tokens/tokenized positions this contract
* manages on a *persistent* basis (e.g. not just for swapping back to
* want ephemerally).
*
* NOTE: Do *not* include `want`, already included in `sweep` below.
*
* Example:
* ```
* function protectedTokens() internal override view returns (address[] memory) {
* address[] memory protected = new address[](3);
* protected[0] = tokenA;
* protected[1] = tokenB;
* protected[2] = tokenC;
* return protected;
* }
* ```
*/
function protectedTokens() internal view virtual returns (address[] memory);
/**
* @notice
* Removes tokens from this Strategy that are not the type of tokens
* managed by this Strategy. This may be used in case of accidentally
* sending the wrong kind of token to this Strategy.
*
* Tokens will be sent to `governance()`.
*
* This will fail if an attempt is made to sweep `want`, or any tokens
* that are protected by this Strategy.
*
* This may only be called by governance.
* @dev
* Implement `protectedTokens()` to specify any additional tokens that
* should be protected from sweeping in addition to `want`.
* @param _token The token to transfer out of this vault.
*/
function sweep(address _token) external onlyGovernance {
require(_token != address(want), "!want");
require(_token != address(vault), "!shares");
address[] memory _protectedTokens = protectedTokens();
for (uint256 i; i < _protectedTokens.length; i++) require(_token != _protectedTokens[i], "!protected");
IERC20(_token).safeTransfer(governance(), IERC20(_token).balanceOf(address(this)));
}
}
abstract contract BaseStrategyInitializable is BaseStrategy {
bool public isOriginal = true;
event Cloned(address indexed clone);
constructor(address _vault) BaseStrategy(_vault) {}
function initialize(
address _vault,
address _strategist,
address _rewards,
address _keeper
) external virtual {
_initialize(_vault, _strategist, _rewards, _keeper);
}
function clone(address _vault) external returns (address) {
return clone(_vault, msg.sender, msg.sender, msg.sender);
}
function clone(
address _vault,
address _strategist,
address _rewards,
address _keeper
) public returns (address newStrategy) {
require(isOriginal, "!clone");
// Copied from https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol
bytes20 addressBytes = bytes20(address(this));
assembly {
// EIP-1167 bytecode
let clone_code := mload(0x40)
mstore(clone_code, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(clone_code, 0x14), addressBytes)
mstore(add(clone_code, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
newStrategy := create(0, clone_code, 0x37)
}
BaseStrategyInitializable(newStrategy).initialize(_vault, _strategist, _rewards, _keeper);
emit Cloned(newStrategy);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
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");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
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");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* 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}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* 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 value {ERC20} uses, unless this function is
* 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 {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @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);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @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
* ====
*
* [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://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(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);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @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.
*/
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].
*/
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);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with 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;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.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);
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_yVault","type":"address"},{"internalType":"string","name":"_strategyName","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"clone","type":"address"}],"name":"Cloned","type":"event"},{"anonymous":false,"inputs":[],"name":"EmergencyExitEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"triggerState","type":"bool"}],"name":"ForcedHarvestTrigger","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"profit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"loss","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debtPayment","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debtOutstanding","type":"uint256"}],"name":"Harvested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"","type":"bool"}],"name":"SetDoHealthCheck","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"","type":"address"}],"name":"SetHealthCheck","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"baseFeeOracle","type":"address"}],"name":"UpdatedBaseFeeOracle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"creditThreshold","type":"uint256"}],"name":"UpdatedCreditThreshold","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newKeeper","type":"address"}],"name":"UpdatedKeeper","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"delay","type":"uint256"}],"name":"UpdatedMaxReportDelay","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"metadataURI","type":"string"}],"name":"UpdatedMetadataURI","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"delay","type":"uint256"}],"name":"UpdatedMinReportDelay","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"rewards","type":"address"}],"name":"UpdatedRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newStrategist","type":"address"}],"name":"UpdatedStrategist","type":"event"},{"inputs":[],"name":"apiVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"balanceOfWant","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseFeeOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimableProfitInUsdc","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimableProfits","outputs":[{"internalType":"uint256","name":"profits","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_strategist","type":"address"},{"internalType":"address","name":"_rewards","type":"address"},{"internalType":"address","name":"_keeper","type":"address"},{"internalType":"address","name":"_yVault","type":"address"},{"internalType":"string","name":"_strategyName","type":"string"}],"name":"cloneRouterStrategy","outputs":[{"internalType":"address","name":"newStrategy","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"creditThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"delegatedAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"doHealthCheck","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dustThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emergencyExit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"estimatedTotalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amtInWei","type":"uint256"}],"name":"ethToWant","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"forceHarvestTriggerOnce","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"harvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"harvestProfitMaxInUsdc","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"harvestProfitMinInUsdc","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"callCostinEth","type":"uint256"}],"name":"harvestTrigger","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"healthCheck","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_strategist","type":"address"},{"internalType":"address","name":"_rewards","type":"address"},{"internalType":"address","name":"_keeper","type":"address"},{"internalType":"address","name":"_yVault","type":"address"},{"internalType":"string","name":"_strategyName","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isBaseFeeAcceptable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isOriginal","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keeper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxLoss","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxReportDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadataURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newStrategy","type":"address"}],"name":"migrate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minReportDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewards","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_baseFeeOracle","type":"address"}],"name":"setBaseFeeOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_creditThreshold","type":"uint256"}],"name":"setCreditThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_doHealthCheck","type":"bool"}],"name":"setDoHealthCheck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_dustThreshold","type":"uint256"}],"name":"setDustThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setEmergencyExit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_forceHarvestTriggerOnce","type":"bool"}],"name":"setForceHarvestTriggerOnce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_harvestProfitMinInUsdc","type":"uint256"},{"internalType":"uint256","name":"_harvestProfitMaxInUsdc","type":"uint256"}],"name":"setHarvestTriggerParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_healthCheck","type":"address"}],"name":"setHealthCheck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_keeper","type":"address"}],"name":"setKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxLoss","type":"uint256"}],"name":"setMaxLoss","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_delay","type":"uint256"}],"name":"setMaxReportDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_metadataURI","type":"string"}],"name":"setMetadataURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_delay","type":"uint256"}],"name":"setMinReportDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rewards","type":"address"}],"name":"setRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategist","type":"address"}],"name":"setStrategist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shareValueHelper","outputs":[{"internalType":"contract IHelper","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strategist","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":[],"name":"tend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"callCostInWei","type":"uint256"}],"name":"tendTrigger","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"valueOfInvestment","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"contract VaultAPI","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"want","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountNeeded","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"_loss","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawFromYVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"yVault","outputs":[{"internalType":"contract IVault","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60806040526010805460ff191660011790553480156200001e57600080fd5b506040516200400a3803806200400a833981016040819052620000419162000752565b82620000508133808062000066565b506200005d8282620002d1565b50505062000b87565b6006546001600160a01b031615620000c55760405162461bcd60e51b815260206004820152601c60248201527f537472617465677920616c726561647920696e697469616c697a65640000000060448201526064015b60405180910390fd5b600280546001600160a01b0319166001600160a01b03861690811790915560408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156200011f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000145919062000832565b600680546001600160a01b0319166001600160a01b039290921691821790556200017f90856000196200031b602090811b62001d4717901c565b600380546001600160a01b038086166001600160a01b031992831617909255600480548584169083161781556005805485851693169290921790915562278d006008556002546040805163313ce56760e01b81529051919093169263313ce56792818101926020929091908290030181865afa15801562000204573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022a919062000857565b6200023790600a62000986565b6200024690620f424062000994565b600a556002546004805460405163095ea7b360e01b81526001600160a01b039182169281019290925260001960248301529091169063095ea7b3906044016020604051808303816000875af1158015620002a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002ca9190620009b6565b5050505050565b600b8054610100600160a81b0319166101006001600160a01b038516021790556011620002ff828262000a68565b505064012a05f200600d5550640ba43b7400600e55600a600f55565b801580620003995750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa15801562000371573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000397919062000857565b155b6200040d5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401620000bc565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152620004659185916200046a16565b505050565b6000620004c6826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166200054860201b62001e94179092919060201c565b805190915015620004655780806020019051810190620004e79190620009b6565b620004655760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401620000bc565b606062000559848460008562000561565b949350505050565b606082471015620005c45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401620000bc565b600080866001600160a01b03168587604051620005e2919062000b34565b60006040518083038185875af1925050503d806000811462000621576040519150601f19603f3d011682016040523d82523d6000602084013e62000626565b606091505b5090925090506200063a8783838762000645565b979650505050505050565b60608315620006b9578251600003620006b1576001600160a01b0385163b620006b15760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620000bc565b508162000559565b620005598383815115620006d05781518083602001fd5b8060405162461bcd60e51b8152600401620000bc919062000b52565b80516001600160a01b03811681146200070457600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200073c57818101518382015260200162000722565b838111156200074c576000848401525b50505050565b6000806000606084860312156200076857600080fd5b6200077384620006ec565b92506200078360208501620006ec565b60408501519092506001600160401b0380821115620007a157600080fd5b818601915086601f830112620007b657600080fd5b815181811115620007cb57620007cb62000709565b604051601f8201601f19908116603f01168101908382118183101715620007f657620007f662000709565b816040528281528960208487010111156200081057600080fd5b620008238360208301602088016200071f565b80955050505050509250925092565b6000602082840312156200084557600080fd5b6200085082620006ec565b9392505050565b6000602082840312156200086a57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600181815b80851115620008c8578160001904821115620008ac57620008ac62000871565b80851615620008ba57918102915b93841c93908002906200088c565b509250929050565b600082620008e15750600162000980565b81620008f05750600062000980565b8160018114620009095760028114620009145762000934565b600191505062000980565b60ff84111562000928576200092862000871565b50506001821b62000980565b5060208310610133831016604e8410600b841016171562000959575081810a62000980565b62000965838362000887565b80600019048211156200097c576200097c62000871565b0290505b92915050565b6000620008508383620008d0565b6000816000190483118215151615620009b157620009b162000871565b500290565b600060208284031215620009c957600080fd5b815180151581146200085057600080fd5b600181811c90821680620009ef57607f821691505b60208210810362000a1057634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200046557600081815260208120601f850160051c8101602086101562000a3f5750805b601f850160051c820191505b8181101562000a605782815560010162000a4b565b505050505050565b81516001600160401b0381111562000a845762000a8462000709565b62000a9c8162000a958454620009da565b8462000a16565b602080601f83116001811462000ad4576000841562000abb5750858301515b600019600386901b1c1916600185901b17855562000a60565b600085815260208120601f198616915b8281101562000b055788860151825594840194600190910190840162000ae4565b508582101562000b245787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000825162000b488184602087016200071f565b9190910192915050565b602081526000825180602084015262000b738160408501602087016200071f565b601f01601f19169190910160400192915050565b6134738062000b976000396000f3fe608060405234801561001057600080fd5b50600436106103835760003560e01c80638aa091f5116101de578063c1a3d44c1161010f578063ee6497f1116100ad578063fa4e2df91161007c578063fa4e2df91461070e578063fbfa77cf14610717578063fcf2d0ad1461072a578063fe2508a61461073257600080fd5b8063ee6497f1146106d8578063efbb5cb0146106eb578063f017c92f146106f3578063f5f5ed171461070657600080fd5b8063d6cb1f6f116100e9578063d6cb1f6f1461068e578063e8462e8f146106a9578063ec38a862146106b2578063ed882c2b146106c557600080fd5b8063c1a3d44c14610660578063c7b9d53014610668578063ce5494bb1461067b57600080fd5b8063a763cf5b1161017c578063aced166111610156578063aced16611461061a578063ad7e55ba1461062d578063b252720b14610640578063b57621141461065857600080fd5b8063a763cf5b146105f1578063aa5480cf146105fe578063ac00ff261461060757600080fd5b806395326e2d116101b857806395326e2d146105ba57806395e80c50146105c25780639ec5a894146105cb5780639f450b5a146105de57600080fd5b80638aa091f51461058c5780638cb14bff1461059f5780638e6350e2146105b257600080fd5b806333303f8e116102b8578063650d188011610256578063748747e611610230578063748747e614610540578063750521f514610553578063780022a014610566578063826cddf61461057457600080fd5b8063650d1880146105125780636718835f146105265780636f392ce71461053357600080fd5b80634641257d116102925780634641257d146104e15780635641ec03146104e95780635783fe39146104f65780635d130ec6146104ff57600080fd5b806333303f8e146104ae57806339a172a8146104c6578063440368a3146104d957600080fd5b80631fe4a6861161032557806325829410116102ff578063258294101461046957806328b7ccf71461048a578063299b1e25146104935780632e1a7d4d1461049b57600080fd5b80631fe4a6861461042b57806322f3e2d41461043e57806324be66281461045657600080fd5b8063090c492211610361578063090c4922146103c35780630ada4dab146103da57806311bc8245146103ed5780631f1fcd511461040057600080fd5b806301681a621461038857806303ee438c1461039d57806306fdde03146103bb575b600080fd5b61039b610396366004612c6c565b610745565b005b6103a56108f0565b6040516103b29190612ce8565b60405180910390f35b6103a561097e565b6103cc600d5481565b6040519081526020016103b2565b61039b6103e8366004612d09565b610a10565b61039b6103fb366004612c6c565b610a60565b600654610413906001600160a01b031681565b6040516001600160a01b0390911681526020016103b2565b600354610413906001600160a01b031681565b610446610acc565b60405190151581526020016103b2565b61039b610464366004612d26565b610b5a565b60408051808201909152600581526418171a171b60d91b60208201526103a5565b6103cc60085481565b6103cc610b67565b6103cc6104a9366004612d26565b610b98565b600b546104139061010090046001600160a01b031681565b61039b6104d4366004612d26565b610c0c565b61039b610c49565b61039b610cc7565b6009546104469060ff1681565b6103cc600c5481565b61039b61050d366004612db0565b611075565b610446610520366004612d26565b50600090565b6001546104469060ff1681565b6010546104469060ff1681565b61039b61054e366004612c6c565b6110ae565b61039b610561366004612ea1565b611117565b6103cc610520366004612d26565b6009546104139061010090046001600160a01b031681565b61041361059a366004612db0565b61116a565b61039b6105ad366004612d26565b61126e565b6103cc611282565b6104466112f9565b6103cc60075481565b600454610413906001600160a01b031681565b61039b6105ec366004612c6c565b61138e565b600b546104469060ff1681565b6103cc600a5481565b61039b610615366004612d09565b6113ec565b600554610413906001600160a01b031681565b61039b61063b366004612d26565b61143c565b6001546104139061010090046001600160a01b031681565b6103cc61149a565b6103cc6115c9565b61039b610676366004612c6c565b611637565b61039b610689366004612c6c565b6116a0565b61041373444443bae5bb8640677a8cdf94cb8879fec948ec81565b6103cc600f5481565b61039b6106c0366004612c6c565b6117c8565b6104466106d3366004612d26565b611926565b61039b6106e6366004612f13565b611abe565b6103cc611ad1565b61039b610701366004612d26565b611aed565b6103cc611b2a565b6103cc600e5481565b600254610413906001600160a01b031681565b61039b611beb565b61039b610740366004612d26565b611d0a565b61074d611eab565b6006546001600160a01b03908116908216036107985760405162461bcd60e51b8152602060048201526005602482015264085dd85b9d60da1b60448201526064015b60405180910390fd5b6002546001600160a01b03908116908216036107e05760405162461bcd60e51b81526020600482015260076024820152662173686172657360c81b604482015260640161078f565b606060005b81518110156108675781818151811061080057610800612f35565b60200260200101516001600160a01b0316836001600160a01b0316036108555760405162461bcd60e51b815260206004820152600a602482015269085c1c9bdd1958dd195960b21b604482015260640161078f565b8061085f81612f61565b9150506107e5565b506108ec610873611ed0565b6040516370a0823160e01b81523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa1580156108b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108db9190612f7a565b6001600160a01b0385169190611f3e565b5050565b600080546108fd90612f93565b80601f016020809104026020016040519081016040528092919081815260200182805461092990612f93565b80156109765780601f1061094b57610100808354040283529160200191610976565b820191906000526020600020905b81548152906001019060200180831161095957829003601f168201915b505050505081565b60606011805461098d90612f93565b80601f01602080910402602001604051908101604052809291908181526020018280546109b990612f93565b8015610a065780601f106109db57610100808354040283529160200191610a06565b820191906000526020600020905b8154815290600101906020018083116109e957829003601f168201915b5050505050905090565b610a18611f6e565b600b805460ff19168215159081179091556040519081527f6ad28df1b554fa6cacd46ae82fa811748d53798feeb437ddf234bf3083953319906020015b60405180910390a150565b610a68611f6e565b6040516001600160a01b03821681527fc8db9c35f716b87af1fbb83f03c78646061931269301fd7ba6dcf189b4cdc2fc9060200160405180910390a1600180546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6002546040516339ebf82360e01b815230600482015260009182916001600160a01b03909116906339ebf8239060240161012060405180830381865afa158015610b1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3e9190612fc7565b604001511180610b5557506000610b53611ad1565b115b905090565b610b62611f6e565b600c55565b600080610b72611ad1565b90506000610b7e611282565b905080821115610b8f579003919050565b60009250505090565b6002546000906001600160a01b03163314610bde5760405162461bcd60e51b8152602060048201526006602482015265085d985d5b1d60d21b604482015260640161078f565b6000610be983612010565b600654909350909150610c06906001600160a01b03163383611f3e565b50919050565b610c14612082565b60078190556040518181527fbb2c369a0355a34b02ab5fce0643150c87e1c8dfe7c918d465591879f57948b190602001610a55565b610c5161209e565b6002546040805163bf3759b560e01b81529051610cc5926001600160a01b03169163bf3759b59160048083019260209291908290030181865afa158015610c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc09190612f7a565b6121f3565b565b610ccf61209e565b6000806000600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4b9190612f7a565b60095490915060009060ff1615610da8576000610d66612299565b905082811015610d8157610d7a8184613042565b9350610d96565b82811115610d9657610d938382613042565b94505b610da08484613042565b915050610db9565b610db1826123aa565b919550935090505b600b805460ff19169055604051600081527f6ad28df1b554fa6cacd46ae82fa811748d53798feeb437ddf234bf30839533199060200160405180910390a16002546040516339ebf82360e01b81523060048201526000916001600160a01b0316906339ebf8239060240161012060405180830381865afa158015610e41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e659190612fc7565b60c001516002546040516328766ebf60e21b81526004810188905260248101879052604481018590529192506001600160a01b03169063a1d9bafc906064016020604051808303816000875af1158015610ec3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee79190612f7a565b9250610ef2836121f3565b60015460ff168015610f13575060015461010090046001600160a01b031615155b15610fe55760015460405163c70fa00b60e01b815260048101879052602481018690526044810184905260648101859052608481018390526101009091046001600160a01b03169063c70fa00b9060a401602060405180830381865afa158015610f81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa59190613059565b610fe05760405162461bcd60e51b815260206004820152600c60248201526b216865616c7468636865636b60a01b604482015260640161078f565b611026565b604051600181527ff769f6bf659bbbdabf212d830720ce893eedc57f25ebb8e44edf5b300618a35b9060200160405180910390a16001805460ff1916811790555b6040805186815260208101869052908101839052606081018490527f4c0f499ffe6befa0ca7c826b0916cf87bea98de658013e76938489368d60d5099060800160405180910390a15050505050565b600b5461010090046001600160a01b03161561109057600080fd5b61109c86868686612428565b6110a68282612672565b505050505050565b6110b6612082565b6001600160a01b0381166110c957600080fd5b600580546001600160a01b0319166001600160a01b0383169081179091556040519081527f2f202ddb4a2e345f6323ed90f8fc8559d770a7abbbeee84dde8aca3351fe715490602001610a55565b61111f612082565b600061112c8284836130bc565b507f300e67d5a415b6d015a471d9c7b95dd58f3e8290af965e84e0f845de2996dda6828260405161115e92919061317c565b60405180910390a15050565b60105460009060ff1661117c57600080fd5b604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81523060601b601482018190526e5af43d82803e903d91602b57fd5bf360881b6028830152906037816000f0604051632e89876360e11b81529093506001600160a01b0384169150635d130ec6906111fd908b908b908b908b908b908b906004016131ab565b600060405180830381600087803b15801561121757600080fd5b505af115801561122b573d6000803e3d6000fd5b50506040516001600160a01b03851692507f783540fb4221a3238720dc7038937d0d79982bcf895274aa6ad179f82cf0d53c9150600090a2509695505050505050565b611276611f6e565b61127f816126ba565b50565b6002546040516339ebf82360e01b81523060048201526000916001600160a01b0316906339ebf8239060240161012060405180830381865afa1580156112cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f09190612fc7565b60c00151905090565b60095460009061010090046001600160a01b03166113175750600190565b600960019054906101000a90046001600160a01b03166001600160a01b03166334a9e75c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561136a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b559190613059565b611396611f6e565b60098054610100600160a81b0319166101006001600160a01b038416908102919091179091556040519081527f711be97287cb9ec921887b9be36e148e1a27c6b158547b22b9704ffc54447a0f90602001610a55565b6113f4611f6e565b60405181151581527ff769f6bf659bbbdabf212d830720ce893eedc57f25ebb8e44edf5b300618a35b9060200160405180910390a16001805460ff1916911515919091179055565b611444611f6e565b61271081106114955760405162461bcd60e51b815260206004820152601a60248201527f596f75722073697a6520697320746f6f206d7563682073697a65000000000000604482015260640161078f565b600f55565b600654604051632415d18360e11b81526001600160a01b0390911660048201526000907383d95e0d5f402511db06817aff3f9ea88224b030908290829063482ba30690602401602060405180830381865afa1580156114fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115219190612f7a565b9050600b60019054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611576573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159a9190612f7a565b6115a590600a6132df565b816115ae610b67565b6115b891906132eb565b6115c2919061330a565b9250505090565b6006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a08231906024015b602060405180830381865afa158015611613573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b559190612f7a565b61163f612082565b6001600160a01b03811661165257600080fd5b600380546001600160a01b0319166001600160a01b0383169081179091556040519081527f352ececae6d7d1e6d26bcf2c549dfd55be1637e9b22dc0cf3b71ddb36097a6b490602001610a55565b6002546001600160a01b031633146116b757600080fd5b6002546040805163fbfa77cf60e01b815290516001600160a01b039283169284169163fbfa77cf9160048083019260209291908290030181865afa158015611703573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611727919061332c565b6001600160a01b03161461173a57600080fd5b6117438161286b565b6006546040516370a0823160e01b815230600482015261127f9183916001600160a01b03909116906370a0823190602401602060405180830381865afa158015611791573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b59190612f7a565b6006546001600160a01b03169190611f3e565b6117d06128f9565b6001600160a01b0381166117e357600080fd5b6002546004805460405163095ea7b360e01b81526001600160a01b0391821692810192909252600060248301529091169063095ea7b3906044016020604051808303816000875af115801561183c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118609190613059565b50600480546001600160a01b0319166001600160a01b03838116918217835560025460405163095ea7b360e01b8152938401929092526000196024840152169063095ea7b3906044016020604051808303816000875af11580156118c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ec9190613059565b506040516001600160a01b03821681527fafbb66abf8f3b719799940473a4052a3717cdd8e40fb6c8a3faadab316b1a06990602001610a55565b6000611930610acc565b61193c57506000919050565b600061194661149a565b9050600e5481111561195b5750600192915050565b6119636112f9565b6119705750600092915050565b600b5460ff16156119845750600192915050565b600d548111156119975750600192915050565b6002546040516339ebf82360e01b81523060048201526000916001600160a01b0316906339ebf8239060240161012060405180830381865afa1580156119e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a059190612fc7565b90506008548160a0015142611a1a9190613042565b1115611a2a575060019392505050565b600a54600260009054906101000a90046001600160a01b03166001600160a01b031663112c1f9b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa49190612f7a565b1115611ab4575060019392505050565b5060009392505050565b611ac6611f6e565b600d91909155600e55565b6000611adb611b2a565b611ae36115c9565b610b559190613349565b611af5612082565b60088190556040518181527f5430e11864ad7aa9775b07d12657fe52df9aa2ba734355bd8ef8747be2c800c590602001610a55565b600b546040516370a0823160e01b815230600482015260009173444443bae5bb8640677a8cdf94cb8879fec948ec9163d3d83fa69161010090046001600160a01b03169081906370a0823190602401602060405180830381865afa158015611b96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bba9190612f7a565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016115f6565b611bf3612932565b6009805460ff191660011790556002546040516339ebf82360e01b81523060048201526001600160a01b03909116906339ebf8239060240161012060405180830381865afa158015611c49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c6d9190612fc7565b6040015115611cdf57600260009054906101000a90046001600160a01b03166001600160a01b031663a0e4af9a6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611cc657600080fd5b505af1158015611cda573d6000803e3d6000fd5b505050505b6040517f97e963041e952738788b9d4871d854d282065b8f90a464928d6528f2e9a4fd0b90600090a1565b611d12611f6e565b600a8190556040518181527fe5ef7832c564a10cbe7b4f1e01ac33a406cb63fcf430a97a9af8616d150af5f390602001610a55565b801580611dc15750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611d9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dbf9190612f7a565b155b611e2c5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606482015260840161078f565b6040516001600160a01b038316602482015260448101829052611e8f90849063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261294e565b505050565b6060611ea38484600085612a20565b949350505050565b611eb3611ed0565b6001600160a01b0316336001600160a01b031614610cc557600080fd5b60025460408051635aa6e67560e01b815290516000926001600160a01b031691635aa6e6759160048083019260209291908290030181865afa158015611f1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b55919061332c565b6040516001600160a01b038316602482015260448101829052611e8f90849063a9059cbb60e01b90606401611e58565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fe5919061332c565b6001600160a01b0316336001600160a01b031614806120075750611eb3611ed0565b610cc557600080fd5b600080600061201d6115c9565b905083811061203157509192600092509050565b80840361203d816126ba565b60006120476115c9565b90508086111561207657600061205d8288613042565b9050819550600f54811015612070578094505b5061207a565b8594505b505050915091565b6003546001600160a01b03163314806120075750611eb3611ed0565b6005546001600160a01b03163314806120c157506003546001600160a01b031633145b806120e457506120cf611ed0565b6001600160a01b0316336001600160a01b0316145b806121765750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa15801561213d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612161919061332c565b6001600160a01b0316336001600160a01b0316145b806120075750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121cf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eb3919061332c565b60095460ff16156122015750565b600061220b6115c9565b905080156108ec57600b54600654612235916001600160a01b036101009091048116911683612afb565b600b60019054906101000a90046001600160a01b03166001600160a01b031663d0e30db06040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561228557600080fd5b505af11580156110a6573d6000803e3d6000fd5b600b546040516370a0823160e01b815230600482015260009182916101009091046001600160a01b0316906370a0823190602401602060405180830381865afa1580156122ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061230e9190612f7a565b9050801561239c57600b54600c54604051631cc6d2f960e31b81526004810184905230602482015260448101919091526101009091046001600160a01b03169063e63697c8906064016020604051808303816000875af1158015612376573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239a9190612f7a565b505b6123a46115c9565b91505090565b6000806000806123b8611ad1565b905060006123c4611282565b905080821061241957808203945085925060006123e18487613349565b905060006123ee82612010565b509050808211156124125780851061240c5780945060009650612412565b84810396505b505061241f565b81810393505b50509193909250565b6006546001600160a01b0316156124815760405162461bcd60e51b815260206004820152601c60248201527f537472617465677920616c726561647920696e697469616c697a656400000000604482015260640161078f565b600280546001600160a01b0319166001600160a01b03861690811790915560408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156124da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124fe919061332c565b600680546001600160a01b0319166001600160a01b0392909216918217905561252a9085600019611d47565b600380546001600160a01b038086166001600160a01b031992831617909255600480548584169083161781556005805485851693169290921790915562278d006008556002546040805163313ce56760e01b81529051919093169263313ce56792818101926020929091908290030181865afa1580156125ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d29190612f7a565b6125dd90600a6132df565b6125ea90620f42406132eb565b600a556002546004805460405163095ea7b360e01b81526001600160a01b039182169281019290925260001960248301529091169063095ea7b3906044016020604051808303816000875af1158015612647573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061266b9190613059565b5050505050565b600b8054610100600160a81b0319166101006001600160a01b03851602179055601161269e8282613361565b505064012a05f200600d5550640ba43b7400600e55600a600f55565b806000036126c55750565b600b546040516370a0823160e01b815230600482015260009161010090046001600160a01b0316906370a0823190602401602060405180830381865afa158015612713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127379190612f7a565b600b54604051632967214160e21b81526101009091046001600160a01b03166004820152602481018490529091506000906127d29073444443bae5bb8640677a8cdf94cb8879fec948ec9063a59c850490604401602060405180830381865afa1580156127a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127cc9190612f7a565b83612b9f565b9050806000036127e157505050565b600b54600c54604051631cc6d2f960e31b81526004810184905230602482015260448101919091526101009091046001600160a01b03169063e63697c8906064016020604051808303816000875af1158015612841573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128659190612f7a565b50505050565b600b546040516370a0823160e01b815230600482015261127f9183916101009091046001600160a01b0316906370a0823190602401602060405180830381865afa1580156128bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128e19190612f7a565b600b5461010090046001600160a01b03169190611f3e565b612901611ed0565b6001600160a01b0316336001600160a01b0316148061200757506003546001600160a01b03163314610cc557600080fd5b6003546001600160a01b03163314806120e457506120cf611ed0565b60006129a3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611e949092919063ffffffff16565b805190915015611e8f57808060200190518101906129c19190613059565b611e8f5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161078f565b606082471015612a815760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161078f565b600080866001600160a01b03168587604051612a9d9190613421565b60006040518083038185875af1925050503d8060008114612ada576040519150601f19603f3d011682016040523d82523d6000602084013e612adf565b606091505b5091509150612af087838387612bb9565b979650505050505050565b604051636eb1769f60e11b81523060048201526001600160a01b03848116602483015282919084169063dd62ed3e90604401602060405180830381865afa158015612b4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6e9190612f7a565b1015611e8f57612b896001600160a01b038316846000611d47565b611e8f6001600160a01b03831684600019611d47565b6000818310612bae5781612bb0565b825b90505b92915050565b60608315612c28578251600003612c21576001600160a01b0385163b612c215760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161078f565b5081611ea3565b611ea38383815115612c3d5781518083602001fd5b8060405162461bcd60e51b815260040161078f9190612ce8565b6001600160a01b038116811461127f57600080fd5b600060208284031215612c7e57600080fd5b8135612c8981612c57565b9392505050565b60005b83811015612cab578181015183820152602001612c93565b838111156128655750506000910152565b60008151808452612cd4816020860160208601612c90565b601f01601f19169290920160200192915050565b602081526000612bb06020830184612cbc565b801515811461127f57600080fd5b600060208284031215612d1b57600080fd5b8135612c8981612cfb565b600060208284031215612d3857600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715612d7957612d79612d3f565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612da857612da8612d3f565b604052919050565b60008060008060008060c08789031215612dc957600080fd5b8635612dd481612c57565b9550602087810135612de581612c57565b95506040880135612df581612c57565b94506060880135612e0581612c57565b93506080880135612e1581612c57565b925060a088013567ffffffffffffffff80821115612e3257600080fd5b818a0191508a601f830112612e4657600080fd5b813581811115612e5857612e58612d3f565b612e6a601f8201601f19168501612d7f565b91508082528b84828501011115612e8057600080fd5b80848401858401376000848284010152508093505050509295509295509295565b60008060208385031215612eb457600080fd5b823567ffffffffffffffff80821115612ecc57600080fd5b818501915085601f830112612ee057600080fd5b813581811115612eef57600080fd5b866020828501011115612f0157600080fd5b60209290920196919550909350505050565b60008060408385031215612f2657600080fd5b50508035926020909101359150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201612f7357612f73612f4b565b5060010190565b600060208284031215612f8c57600080fd5b5051919050565b600181811c90821680612fa757607f821691505b602082108103610c0657634e487b7160e01b600052602260045260246000fd5b60006101208284031215612fda57600080fd5b612fe2612d55565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152508091505092915050565b60008282101561305457613054612f4b565b500390565b60006020828403121561306b57600080fd5b8151612c8981612cfb565b601f821115611e8f57600081815260208120601f850160051c8101602086101561309d5750805b601f850160051c820191505b818110156110a6578281556001016130a9565b67ffffffffffffffff8311156130d4576130d4612d3f565b6130e8836130e28354612f93565b83613076565b6000601f84116001811461311c57600085156131045750838201355b600019600387901b1c1916600186901b17835561266b565b600083815260209020601f19861690835b8281101561314d578685013582556020948501946001909201910161312d565b508682101561316a5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b6001600160a01b0387811682528681166020830152858116604083015284811660608301528316608082015260c060a082018190526000906131ef90830184612cbc565b98975050505050505050565b600181815b8085111561323657816000190482111561321c5761321c612f4b565b8085161561322957918102915b93841c9390800290613200565b509250929050565b60008261324d57506001612bb3565b8161325a57506000612bb3565b8160018114613270576002811461327a57613296565b6001915050612bb3565b60ff84111561328b5761328b612f4b565b50506001821b612bb3565b5060208310610133831016604e8410600b84101617156132b9575081810a612bb3565b6132c383836131fb565b80600019048211156132d7576132d7612f4b565b029392505050565b6000612bb0838361323e565b600081600019048311821515161561330557613305612f4b565b500290565b60008261332757634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561333e57600080fd5b8151612c8981612c57565b6000821982111561335c5761335c612f4b565b500190565b815167ffffffffffffffff81111561337b5761337b612d3f565b61338f816133898454612f93565b84613076565b602080601f8311600181146133c457600084156133ac5750858301515b600019600386901b1c1916600185901b1785556110a6565b600085815260208120601f198616915b828110156133f3578886015182559484019460019091019084016133d4565b50858210156134115787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008251613433818460208701612c90565b919091019291505056fea264697066735822122036aa1d7c57341d491068eb52b81162d96db22a453d81893d0bf4e46d9779124664736f6c634300080f0033000000000000000000000000e537b5cc158eb71037d4125bdd7538421981e6aa0000000000000000000000008078198fc424986ae89ce4a910fc109587b6abf3000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000185374726174656779526f7574657256322d3343727970746f0000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103835760003560e01c80638aa091f5116101de578063c1a3d44c1161010f578063ee6497f1116100ad578063fa4e2df91161007c578063fa4e2df91461070e578063fbfa77cf14610717578063fcf2d0ad1461072a578063fe2508a61461073257600080fd5b8063ee6497f1146106d8578063efbb5cb0146106eb578063f017c92f146106f3578063f5f5ed171461070657600080fd5b8063d6cb1f6f116100e9578063d6cb1f6f1461068e578063e8462e8f146106a9578063ec38a862146106b2578063ed882c2b146106c557600080fd5b8063c1a3d44c14610660578063c7b9d53014610668578063ce5494bb1461067b57600080fd5b8063a763cf5b1161017c578063aced166111610156578063aced16611461061a578063ad7e55ba1461062d578063b252720b14610640578063b57621141461065857600080fd5b8063a763cf5b146105f1578063aa5480cf146105fe578063ac00ff261461060757600080fd5b806395326e2d116101b857806395326e2d146105ba57806395e80c50146105c25780639ec5a894146105cb5780639f450b5a146105de57600080fd5b80638aa091f51461058c5780638cb14bff1461059f5780638e6350e2146105b257600080fd5b806333303f8e116102b8578063650d188011610256578063748747e611610230578063748747e614610540578063750521f514610553578063780022a014610566578063826cddf61461057457600080fd5b8063650d1880146105125780636718835f146105265780636f392ce71461053357600080fd5b80634641257d116102925780634641257d146104e15780635641ec03146104e95780635783fe39146104f65780635d130ec6146104ff57600080fd5b806333303f8e146104ae57806339a172a8146104c6578063440368a3146104d957600080fd5b80631fe4a6861161032557806325829410116102ff578063258294101461046957806328b7ccf71461048a578063299b1e25146104935780632e1a7d4d1461049b57600080fd5b80631fe4a6861461042b57806322f3e2d41461043e57806324be66281461045657600080fd5b8063090c492211610361578063090c4922146103c35780630ada4dab146103da57806311bc8245146103ed5780631f1fcd511461040057600080fd5b806301681a621461038857806303ee438c1461039d57806306fdde03146103bb575b600080fd5b61039b610396366004612c6c565b610745565b005b6103a56108f0565b6040516103b29190612ce8565b60405180910390f35b6103a561097e565b6103cc600d5481565b6040519081526020016103b2565b61039b6103e8366004612d09565b610a10565b61039b6103fb366004612c6c565b610a60565b600654610413906001600160a01b031681565b6040516001600160a01b0390911681526020016103b2565b600354610413906001600160a01b031681565b610446610acc565b60405190151581526020016103b2565b61039b610464366004612d26565b610b5a565b60408051808201909152600581526418171a171b60d91b60208201526103a5565b6103cc60085481565b6103cc610b67565b6103cc6104a9366004612d26565b610b98565b600b546104139061010090046001600160a01b031681565b61039b6104d4366004612d26565b610c0c565b61039b610c49565b61039b610cc7565b6009546104469060ff1681565b6103cc600c5481565b61039b61050d366004612db0565b611075565b610446610520366004612d26565b50600090565b6001546104469060ff1681565b6010546104469060ff1681565b61039b61054e366004612c6c565b6110ae565b61039b610561366004612ea1565b611117565b6103cc610520366004612d26565b6009546104139061010090046001600160a01b031681565b61041361059a366004612db0565b61116a565b61039b6105ad366004612d26565b61126e565b6103cc611282565b6104466112f9565b6103cc60075481565b600454610413906001600160a01b031681565b61039b6105ec366004612c6c565b61138e565b600b546104469060ff1681565b6103cc600a5481565b61039b610615366004612d09565b6113ec565b600554610413906001600160a01b031681565b61039b61063b366004612d26565b61143c565b6001546104139061010090046001600160a01b031681565b6103cc61149a565b6103cc6115c9565b61039b610676366004612c6c565b611637565b61039b610689366004612c6c565b6116a0565b61041373444443bae5bb8640677a8cdf94cb8879fec948ec81565b6103cc600f5481565b61039b6106c0366004612c6c565b6117c8565b6104466106d3366004612d26565b611926565b61039b6106e6366004612f13565b611abe565b6103cc611ad1565b61039b610701366004612d26565b611aed565b6103cc611b2a565b6103cc600e5481565b600254610413906001600160a01b031681565b61039b611beb565b61039b610740366004612d26565b611d0a565b61074d611eab565b6006546001600160a01b03908116908216036107985760405162461bcd60e51b8152602060048201526005602482015264085dd85b9d60da1b60448201526064015b60405180910390fd5b6002546001600160a01b03908116908216036107e05760405162461bcd60e51b81526020600482015260076024820152662173686172657360c81b604482015260640161078f565b606060005b81518110156108675781818151811061080057610800612f35565b60200260200101516001600160a01b0316836001600160a01b0316036108555760405162461bcd60e51b815260206004820152600a602482015269085c1c9bdd1958dd195960b21b604482015260640161078f565b8061085f81612f61565b9150506107e5565b506108ec610873611ed0565b6040516370a0823160e01b81523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa1580156108b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108db9190612f7a565b6001600160a01b0385169190611f3e565b5050565b600080546108fd90612f93565b80601f016020809104026020016040519081016040528092919081815260200182805461092990612f93565b80156109765780601f1061094b57610100808354040283529160200191610976565b820191906000526020600020905b81548152906001019060200180831161095957829003601f168201915b505050505081565b60606011805461098d90612f93565b80601f01602080910402602001604051908101604052809291908181526020018280546109b990612f93565b8015610a065780601f106109db57610100808354040283529160200191610a06565b820191906000526020600020905b8154815290600101906020018083116109e957829003601f168201915b5050505050905090565b610a18611f6e565b600b805460ff19168215159081179091556040519081527f6ad28df1b554fa6cacd46ae82fa811748d53798feeb437ddf234bf3083953319906020015b60405180910390a150565b610a68611f6e565b6040516001600160a01b03821681527fc8db9c35f716b87af1fbb83f03c78646061931269301fd7ba6dcf189b4cdc2fc9060200160405180910390a1600180546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6002546040516339ebf82360e01b815230600482015260009182916001600160a01b03909116906339ebf8239060240161012060405180830381865afa158015610b1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3e9190612fc7565b604001511180610b5557506000610b53611ad1565b115b905090565b610b62611f6e565b600c55565b600080610b72611ad1565b90506000610b7e611282565b905080821115610b8f579003919050565b60009250505090565b6002546000906001600160a01b03163314610bde5760405162461bcd60e51b8152602060048201526006602482015265085d985d5b1d60d21b604482015260640161078f565b6000610be983612010565b600654909350909150610c06906001600160a01b03163383611f3e565b50919050565b610c14612082565b60078190556040518181527fbb2c369a0355a34b02ab5fce0643150c87e1c8dfe7c918d465591879f57948b190602001610a55565b610c5161209e565b6002546040805163bf3759b560e01b81529051610cc5926001600160a01b03169163bf3759b59160048083019260209291908290030181865afa158015610c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc09190612f7a565b6121f3565b565b610ccf61209e565b6000806000600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4b9190612f7a565b60095490915060009060ff1615610da8576000610d66612299565b905082811015610d8157610d7a8184613042565b9350610d96565b82811115610d9657610d938382613042565b94505b610da08484613042565b915050610db9565b610db1826123aa565b919550935090505b600b805460ff19169055604051600081527f6ad28df1b554fa6cacd46ae82fa811748d53798feeb437ddf234bf30839533199060200160405180910390a16002546040516339ebf82360e01b81523060048201526000916001600160a01b0316906339ebf8239060240161012060405180830381865afa158015610e41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e659190612fc7565b60c001516002546040516328766ebf60e21b81526004810188905260248101879052604481018590529192506001600160a01b03169063a1d9bafc906064016020604051808303816000875af1158015610ec3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee79190612f7a565b9250610ef2836121f3565b60015460ff168015610f13575060015461010090046001600160a01b031615155b15610fe55760015460405163c70fa00b60e01b815260048101879052602481018690526044810184905260648101859052608481018390526101009091046001600160a01b03169063c70fa00b9060a401602060405180830381865afa158015610f81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa59190613059565b610fe05760405162461bcd60e51b815260206004820152600c60248201526b216865616c7468636865636b60a01b604482015260640161078f565b611026565b604051600181527ff769f6bf659bbbdabf212d830720ce893eedc57f25ebb8e44edf5b300618a35b9060200160405180910390a16001805460ff1916811790555b6040805186815260208101869052908101839052606081018490527f4c0f499ffe6befa0ca7c826b0916cf87bea98de658013e76938489368d60d5099060800160405180910390a15050505050565b600b5461010090046001600160a01b03161561109057600080fd5b61109c86868686612428565b6110a68282612672565b505050505050565b6110b6612082565b6001600160a01b0381166110c957600080fd5b600580546001600160a01b0319166001600160a01b0383169081179091556040519081527f2f202ddb4a2e345f6323ed90f8fc8559d770a7abbbeee84dde8aca3351fe715490602001610a55565b61111f612082565b600061112c8284836130bc565b507f300e67d5a415b6d015a471d9c7b95dd58f3e8290af965e84e0f845de2996dda6828260405161115e92919061317c565b60405180910390a15050565b60105460009060ff1661117c57600080fd5b604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81523060601b601482018190526e5af43d82803e903d91602b57fd5bf360881b6028830152906037816000f0604051632e89876360e11b81529093506001600160a01b0384169150635d130ec6906111fd908b908b908b908b908b908b906004016131ab565b600060405180830381600087803b15801561121757600080fd5b505af115801561122b573d6000803e3d6000fd5b50506040516001600160a01b03851692507f783540fb4221a3238720dc7038937d0d79982bcf895274aa6ad179f82cf0d53c9150600090a2509695505050505050565b611276611f6e565b61127f816126ba565b50565b6002546040516339ebf82360e01b81523060048201526000916001600160a01b0316906339ebf8239060240161012060405180830381865afa1580156112cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f09190612fc7565b60c00151905090565b60095460009061010090046001600160a01b03166113175750600190565b600960019054906101000a90046001600160a01b03166001600160a01b03166334a9e75c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561136a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b559190613059565b611396611f6e565b60098054610100600160a81b0319166101006001600160a01b038416908102919091179091556040519081527f711be97287cb9ec921887b9be36e148e1a27c6b158547b22b9704ffc54447a0f90602001610a55565b6113f4611f6e565b60405181151581527ff769f6bf659bbbdabf212d830720ce893eedc57f25ebb8e44edf5b300618a35b9060200160405180910390a16001805460ff1916911515919091179055565b611444611f6e565b61271081106114955760405162461bcd60e51b815260206004820152601a60248201527f596f75722073697a6520697320746f6f206d7563682073697a65000000000000604482015260640161078f565b600f55565b600654604051632415d18360e11b81526001600160a01b0390911660048201526000907383d95e0d5f402511db06817aff3f9ea88224b030908290829063482ba30690602401602060405180830381865afa1580156114fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115219190612f7a565b9050600b60019054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611576573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159a9190612f7a565b6115a590600a6132df565b816115ae610b67565b6115b891906132eb565b6115c2919061330a565b9250505090565b6006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a08231906024015b602060405180830381865afa158015611613573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b559190612f7a565b61163f612082565b6001600160a01b03811661165257600080fd5b600380546001600160a01b0319166001600160a01b0383169081179091556040519081527f352ececae6d7d1e6d26bcf2c549dfd55be1637e9b22dc0cf3b71ddb36097a6b490602001610a55565b6002546001600160a01b031633146116b757600080fd5b6002546040805163fbfa77cf60e01b815290516001600160a01b039283169284169163fbfa77cf9160048083019260209291908290030181865afa158015611703573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611727919061332c565b6001600160a01b03161461173a57600080fd5b6117438161286b565b6006546040516370a0823160e01b815230600482015261127f9183916001600160a01b03909116906370a0823190602401602060405180830381865afa158015611791573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b59190612f7a565b6006546001600160a01b03169190611f3e565b6117d06128f9565b6001600160a01b0381166117e357600080fd5b6002546004805460405163095ea7b360e01b81526001600160a01b0391821692810192909252600060248301529091169063095ea7b3906044016020604051808303816000875af115801561183c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118609190613059565b50600480546001600160a01b0319166001600160a01b03838116918217835560025460405163095ea7b360e01b8152938401929092526000196024840152169063095ea7b3906044016020604051808303816000875af11580156118c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ec9190613059565b506040516001600160a01b03821681527fafbb66abf8f3b719799940473a4052a3717cdd8e40fb6c8a3faadab316b1a06990602001610a55565b6000611930610acc565b61193c57506000919050565b600061194661149a565b9050600e5481111561195b5750600192915050565b6119636112f9565b6119705750600092915050565b600b5460ff16156119845750600192915050565b600d548111156119975750600192915050565b6002546040516339ebf82360e01b81523060048201526000916001600160a01b0316906339ebf8239060240161012060405180830381865afa1580156119e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a059190612fc7565b90506008548160a0015142611a1a9190613042565b1115611a2a575060019392505050565b600a54600260009054906101000a90046001600160a01b03166001600160a01b031663112c1f9b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa49190612f7a565b1115611ab4575060019392505050565b5060009392505050565b611ac6611f6e565b600d91909155600e55565b6000611adb611b2a565b611ae36115c9565b610b559190613349565b611af5612082565b60088190556040518181527f5430e11864ad7aa9775b07d12657fe52df9aa2ba734355bd8ef8747be2c800c590602001610a55565b600b546040516370a0823160e01b815230600482015260009173444443bae5bb8640677a8cdf94cb8879fec948ec9163d3d83fa69161010090046001600160a01b03169081906370a0823190602401602060405180830381865afa158015611b96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bba9190612f7a565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016115f6565b611bf3612932565b6009805460ff191660011790556002546040516339ebf82360e01b81523060048201526001600160a01b03909116906339ebf8239060240161012060405180830381865afa158015611c49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c6d9190612fc7565b6040015115611cdf57600260009054906101000a90046001600160a01b03166001600160a01b031663a0e4af9a6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611cc657600080fd5b505af1158015611cda573d6000803e3d6000fd5b505050505b6040517f97e963041e952738788b9d4871d854d282065b8f90a464928d6528f2e9a4fd0b90600090a1565b611d12611f6e565b600a8190556040518181527fe5ef7832c564a10cbe7b4f1e01ac33a406cb63fcf430a97a9af8616d150af5f390602001610a55565b801580611dc15750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611d9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dbf9190612f7a565b155b611e2c5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606482015260840161078f565b6040516001600160a01b038316602482015260448101829052611e8f90849063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261294e565b505050565b6060611ea38484600085612a20565b949350505050565b611eb3611ed0565b6001600160a01b0316336001600160a01b031614610cc557600080fd5b60025460408051635aa6e67560e01b815290516000926001600160a01b031691635aa6e6759160048083019260209291908290030181865afa158015611f1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b55919061332c565b6040516001600160a01b038316602482015260448101829052611e8f90849063a9059cbb60e01b90606401611e58565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fe5919061332c565b6001600160a01b0316336001600160a01b031614806120075750611eb3611ed0565b610cc557600080fd5b600080600061201d6115c9565b905083811061203157509192600092509050565b80840361203d816126ba565b60006120476115c9565b90508086111561207657600061205d8288613042565b9050819550600f54811015612070578094505b5061207a565b8594505b505050915091565b6003546001600160a01b03163314806120075750611eb3611ed0565b6005546001600160a01b03163314806120c157506003546001600160a01b031633145b806120e457506120cf611ed0565b6001600160a01b0316336001600160a01b0316145b806121765750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa15801561213d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612161919061332c565b6001600160a01b0316336001600160a01b0316145b806120075750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121cf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eb3919061332c565b60095460ff16156122015750565b600061220b6115c9565b905080156108ec57600b54600654612235916001600160a01b036101009091048116911683612afb565b600b60019054906101000a90046001600160a01b03166001600160a01b031663d0e30db06040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561228557600080fd5b505af11580156110a6573d6000803e3d6000fd5b600b546040516370a0823160e01b815230600482015260009182916101009091046001600160a01b0316906370a0823190602401602060405180830381865afa1580156122ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061230e9190612f7a565b9050801561239c57600b54600c54604051631cc6d2f960e31b81526004810184905230602482015260448101919091526101009091046001600160a01b03169063e63697c8906064016020604051808303816000875af1158015612376573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239a9190612f7a565b505b6123a46115c9565b91505090565b6000806000806123b8611ad1565b905060006123c4611282565b905080821061241957808203945085925060006123e18487613349565b905060006123ee82612010565b509050808211156124125780851061240c5780945060009650612412565b84810396505b505061241f565b81810393505b50509193909250565b6006546001600160a01b0316156124815760405162461bcd60e51b815260206004820152601c60248201527f537472617465677920616c726561647920696e697469616c697a656400000000604482015260640161078f565b600280546001600160a01b0319166001600160a01b03861690811790915560408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa1580156124da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124fe919061332c565b600680546001600160a01b0319166001600160a01b0392909216918217905561252a9085600019611d47565b600380546001600160a01b038086166001600160a01b031992831617909255600480548584169083161781556005805485851693169290921790915562278d006008556002546040805163313ce56760e01b81529051919093169263313ce56792818101926020929091908290030181865afa1580156125ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d29190612f7a565b6125dd90600a6132df565b6125ea90620f42406132eb565b600a556002546004805460405163095ea7b360e01b81526001600160a01b039182169281019290925260001960248301529091169063095ea7b3906044016020604051808303816000875af1158015612647573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061266b9190613059565b5050505050565b600b8054610100600160a81b0319166101006001600160a01b03851602179055601161269e8282613361565b505064012a05f200600d5550640ba43b7400600e55600a600f55565b806000036126c55750565b600b546040516370a0823160e01b815230600482015260009161010090046001600160a01b0316906370a0823190602401602060405180830381865afa158015612713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127379190612f7a565b600b54604051632967214160e21b81526101009091046001600160a01b03166004820152602481018490529091506000906127d29073444443bae5bb8640677a8cdf94cb8879fec948ec9063a59c850490604401602060405180830381865afa1580156127a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127cc9190612f7a565b83612b9f565b9050806000036127e157505050565b600b54600c54604051631cc6d2f960e31b81526004810184905230602482015260448101919091526101009091046001600160a01b03169063e63697c8906064016020604051808303816000875af1158015612841573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128659190612f7a565b50505050565b600b546040516370a0823160e01b815230600482015261127f9183916101009091046001600160a01b0316906370a0823190602401602060405180830381865afa1580156128bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128e19190612f7a565b600b5461010090046001600160a01b03169190611f3e565b612901611ed0565b6001600160a01b0316336001600160a01b0316148061200757506003546001600160a01b03163314610cc557600080fd5b6003546001600160a01b03163314806120e457506120cf611ed0565b60006129a3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611e949092919063ffffffff16565b805190915015611e8f57808060200190518101906129c19190613059565b611e8f5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161078f565b606082471015612a815760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161078f565b600080866001600160a01b03168587604051612a9d9190613421565b60006040518083038185875af1925050503d8060008114612ada576040519150601f19603f3d011682016040523d82523d6000602084013e612adf565b606091505b5091509150612af087838387612bb9565b979650505050505050565b604051636eb1769f60e11b81523060048201526001600160a01b03848116602483015282919084169063dd62ed3e90604401602060405180830381865afa158015612b4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6e9190612f7a565b1015611e8f57612b896001600160a01b038316846000611d47565b611e8f6001600160a01b03831684600019611d47565b6000818310612bae5781612bb0565b825b90505b92915050565b60608315612c28578251600003612c21576001600160a01b0385163b612c215760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161078f565b5081611ea3565b611ea38383815115612c3d5781518083602001fd5b8060405162461bcd60e51b815260040161078f9190612ce8565b6001600160a01b038116811461127f57600080fd5b600060208284031215612c7e57600080fd5b8135612c8981612c57565b9392505050565b60005b83811015612cab578181015183820152602001612c93565b838111156128655750506000910152565b60008151808452612cd4816020860160208601612c90565b601f01601f19169290920160200192915050565b602081526000612bb06020830184612cbc565b801515811461127f57600080fd5b600060208284031215612d1b57600080fd5b8135612c8981612cfb565b600060208284031215612d3857600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715612d7957612d79612d3f565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612da857612da8612d3f565b604052919050565b60008060008060008060c08789031215612dc957600080fd5b8635612dd481612c57565b9550602087810135612de581612c57565b95506040880135612df581612c57565b94506060880135612e0581612c57565b93506080880135612e1581612c57565b925060a088013567ffffffffffffffff80821115612e3257600080fd5b818a0191508a601f830112612e4657600080fd5b813581811115612e5857612e58612d3f565b612e6a601f8201601f19168501612d7f565b91508082528b84828501011115612e8057600080fd5b80848401858401376000848284010152508093505050509295509295509295565b60008060208385031215612eb457600080fd5b823567ffffffffffffffff80821115612ecc57600080fd5b818501915085601f830112612ee057600080fd5b813581811115612eef57600080fd5b866020828501011115612f0157600080fd5b60209290920196919550909350505050565b60008060408385031215612f2657600080fd5b50508035926020909101359150565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201612f7357612f73612f4b565b5060010190565b600060208284031215612f8c57600080fd5b5051919050565b600181811c90821680612fa757607f821691505b602082108103610c0657634e487b7160e01b600052602260045260246000fd5b60006101208284031215612fda57600080fd5b612fe2612d55565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152508091505092915050565b60008282101561305457613054612f4b565b500390565b60006020828403121561306b57600080fd5b8151612c8981612cfb565b601f821115611e8f57600081815260208120601f850160051c8101602086101561309d5750805b601f850160051c820191505b818110156110a6578281556001016130a9565b67ffffffffffffffff8311156130d4576130d4612d3f565b6130e8836130e28354612f93565b83613076565b6000601f84116001811461311c57600085156131045750838201355b600019600387901b1c1916600186901b17835561266b565b600083815260209020601f19861690835b8281101561314d578685013582556020948501946001909201910161312d565b508682101561316a5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b6001600160a01b0387811682528681166020830152858116604083015284811660608301528316608082015260c060a082018190526000906131ef90830184612cbc565b98975050505050505050565b600181815b8085111561323657816000190482111561321c5761321c612f4b565b8085161561322957918102915b93841c9390800290613200565b509250929050565b60008261324d57506001612bb3565b8161325a57506000612bb3565b8160018114613270576002811461327a57613296565b6001915050612bb3565b60ff84111561328b5761328b612f4b565b50506001821b612bb3565b5060208310610133831016604e8410600b84101617156132b9575081810a612bb3565b6132c383836131fb565b80600019048211156132d7576132d7612f4b565b029392505050565b6000612bb0838361323e565b600081600019048311821515161561330557613305612f4b565b500290565b60008261332757634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561333e57600080fd5b8151612c8981612c57565b6000821982111561335c5761335c612f4b565b500190565b815167ffffffffffffffff81111561337b5761337b612d3f565b61338f816133898454612f93565b84613076565b602080601f8311600181146133c457600084156133ac5750858301515b600019600386901b1c1916600185901b1785556110a6565b600085815260208120601f198616915b828110156133f3578886015182559484019460019091019084016133d4565b50858210156134115787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008251613433818460208701612c90565b919091019291505056fea264697066735822122036aa1d7c57341d491068eb52b81162d96db22a453d81893d0bf4e46d9779124664736f6c634300080f0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000e537b5cc158eb71037d4125bdd7538421981e6aa0000000000000000000000008078198fc424986ae89ce4a910fc109587b6abf3000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000185374726174656779526f7574657256322d3343727970746f0000000000000000
-----Decoded View---------------
Arg [0] : _vault (address): 0xE537B5cc158EB71037D4125BDD7538421981E6AA
Arg [1] : _yVault (address): 0x8078198Fc424986ae89Ce4a910Fc109587b6aBF3
Arg [2] : _strategyName (string): StrategyRouterV2-3Crypto
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000e537b5cc158eb71037d4125bdd7538421981e6aa
Arg [1] : 0000000000000000000000008078198fc424986ae89ce4a910fc109587b6abf3
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000018
Arg [4] : 5374726174656779526f7574657256322d3343727970746f0000000000000000
Deployed Bytecode Sourcemap
1285:15429:8:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36170:436:9;;;;;;:::i;:::-;;:::i;:::-;;6816:25;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5362:99:8;;;:::i;2013:37::-;;;;;;;;;1299:25:10;;;1287:2;1272:18;2013:37:8;1153:177:10;17426:222:9;;;;;;:::i;:::-;;:::i;13207:159::-;;;;;;:::i;:::-;;:::i;8792:18::-;;;;;-1:-1:-1;;;;;8792:18:9;;;;;;-1:-1:-1;;;;;1882:32:10;;;1864:51;;1852:2;1837:18;8792::9;1704:217:10;8705:25:9;;;;;-1:-1:-1;;;;;8705:25:9;;;21300:146;;;:::i;:::-;;;2299:14:10;;2292:22;2274:41;;2262:2;2247:18;21300:146:9;2134:187:10;15536:98:8;;;;;;:::i;:::-;;:::i;7202:89:9:-;7270:14;;;;;;;;;;;;-1:-1:-1;;;7270:14:9;;;;7202:89;;9779:29;;;;;;6755:325:8;;;:::i;32588:507:9:-;;;;;;:::i;:::-;;:::i;1481:20:8:-;;;;;;;;-1:-1:-1;;;;;1481:20:8;;;15714:151:9;;;;;;:::i;:::-;;:::i;26365:167::-;;;:::i;30625:1729::-;;;:::i;9856:25::-;;;;;;;;;1616:22:8;;;;;;4632:364;;;;;;:::i;:::-;;:::i;25550:497:9:-;;;;;;:::i;:::-;-1:-1:-1;25623:4:9;;25550:497;6869:25;;;;;;;;;2516:29:8;;;;;;;;;14501:170:9;;;;;;:::i;:::-;;:::i;18439:168::-;;;;;;:::i;:::-;;:::i;12059:131:8:-;;;;;;:::i;9938:28:9:-;;;;;;;;-1:-1:-1;;;;;9938:28:9;;;3432:1194:8;;;;;;:::i;:::-;;:::i;10063:117::-;;;;;;:::i;:::-;;:::i;6047:131::-;;;:::i;29645:193:9:-;;;:::i;9632:29::-;;;;;;8736:22;;;;;-1:-1:-1;;;;;8736:22:9;;;17971:175;;;;;;:::i;:::-;;:::i;10100:35::-;;;;;;;;;10015:30;;;;;;13372:168;;;;;;:::i;:::-;;:::i;8764:21::-;;;;;-1:-1:-1;;;;;8764:21:9;;;15845:215:8;;;;;;:::i;:::-;;:::i;6900:26:9:-;;;;;;;;-1:-1:-1;;;;;6900:26:9;;;14602:475:8;;;:::i;6241:108::-;;;:::i;13764:198:9:-;;;;;;:::i;:::-;;:::i;33846:276::-;;;;;;:::i;:::-;;:::i;1793:102:8:-;;1852:42;1793:102;;2362:28;;;;;;14950:261:9;;;;;;:::i;:::-;;:::i;12779:1553:8:-;;;;;;:::i;:::-;;:::i;16441:271::-;;;;;;:::i;:::-;;:::i;5546:184::-;;;:::i;16368:151:9:-;;;;;;:::i;:::-;;:::i;6448:230:8:-;;;:::i;2204:37::-;;;;;;8678:21:9;;;;;-1:-1:-1;;;;;8678:21:9;;;34539:244;;;:::i;16854:187::-;;;;;;:::i;:::-;;:::i;36170:436::-;10444:17;:15;:17::i;:::-;36261:4:::1;::::0;-1:-1:-1;;;;;36261:4:9;;::::1;36243:23:::0;;::::1;::::0;36235:41:::1;;;::::0;-1:-1:-1;;;36235:41:9;;6375:2:10;36235:41:9::1;::::0;::::1;6357:21:10::0;6414:1;6394:18;;;6387:29;-1:-1:-1;;;6432:18:10;;;6425:35;6477:18;;36235:41:9::1;;;;;;;;;36312:5;::::0;-1:-1:-1;;;;;36312:5:9;;::::1;36294:24:::0;;::::1;::::0;36286:44:::1;;;::::0;-1:-1:-1;;;36286:44:9;;6708:2:10;36286:44:9::1;::::0;::::1;6690:21:10::0;6747:1;6727:18;;;6720:29;-1:-1:-1;;;6765:18:10;;;6758:37;6812:18;;36286:44:9::1;6506:330:10::0;36286:44:9::1;11454:20:8::0;36341:33:9::1;36404:102;36424:16;:23;36420:1;:27;36404:102;;;36472:16;36489:1;36472:19;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1::0;;;;;36462:29:9::1;:6;-1:-1:-1::0;;;;;36462:29:9::1;::::0;36454:52:::1;;;::::0;-1:-1:-1;;;36454:52:9;;7175:2:10;36454:52:9::1;::::0;::::1;7157:21:10::0;7214:2;7194:18;;;7187:30;-1:-1:-1;;;7233:18:10;;;7226:40;7283:18;;36454:52:9::1;6973:334:10::0;36454:52:9::1;36449:3:::0;::::1;::::0;::::1;:::i;:::-;;;;36404:102;;;;36517:82;36545:12;:10;:12::i;:::-;36559:39;::::0;-1:-1:-1;;;36559:39:9;;36592:4:::1;36559:39;::::0;::::1;1864:51:10::0;-1:-1:-1;;;;;36559:24:9;::::1;::::0;::::1;::::0;1837:18:10;;36559:39:9::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;36517:27:9;::::1;::::0;:82;:27:::1;:82::i;:::-;36225:381;36170:436:::0;:::o;6816:25::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;5362:99:8:-;5410:13;5442:12;5435:19;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5362:99;:::o;17426:222:9:-;10668:20;:18;:20::i;:::-;17530:23:::1;:50:::0;;-1:-1:-1;;17530:50:9::1;::::0;::::1;;::::0;;::::1;::::0;;;17595:46:::1;::::0;2274:41:10;;;17595:46:9::1;::::0;2262:2:10;2247:18;17595:46:9::1;;;;;;;;17426:222:::0;:::o;13207:159::-;10668:20;:18;:20::i;:::-;13295:28:::1;::::0;-1:-1:-1;;;;;1882:32:10;;1864:51;;13295:28:9::1;::::0;1852:2:10;1837:18;13295:28:9::1;;;;;;;13333:11;:26:::0;;-1:-1:-1;;;;;13333:26:9;;::::1;;;-1:-1:-1::0;;;;;;13333:26:9;;::::1;::::0;;;::::1;::::0;;13207:159::o;21300:146::-;21364:5;;:31;;-1:-1:-1;;;21364:31:9;;21389:4;21364:31;;;1864:51:10;21341:4:9;;;;-1:-1:-1;;;;;21364:5:9;;;;:16;;1837:18:10;;21364:31:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;:45;:75;;;;21438:1;21413:22;:20;:22::i;:::-;:26;21364:75;21357:82;;21300:146;:::o;15536:98:8:-;10668:20:9;:18;:20::i;:::-;15609:7:8::1;:18:::0;15536:98::o;6755:325::-;6804:15;6831:14;6848:22;:20;:22::i;:::-;6831:39;;6880:12;6895:17;:15;:17::i;:::-;6880:32;;6936:4;6927:6;:13;6923:151;;;6994:13;;;6755:325;-1:-1:-1;6755:325:8:o;6923:151::-;7062:1;7052:11;;6821:259;;6755:325;:::o;32588:507:9:-;32702:5;;32647:13;;-1:-1:-1;;;;;32702:5:9;32680:10;:28;32672:47;;;;-1:-1:-1;;;32672:47:9;;9149:2:10;32672:47:9;;;9131:21:10;9188:1;9168:18;;;9161:29;-1:-1:-1;;;9206:18:10;;;9199:36;9252:18;;32672:47:9;8947:329:10;32672:47:9;32803:19;32855:32;32873:13;32855:17;:32::i;:::-;32977:4;;32832:55;;-1:-1:-1;32832:55:9;;-1:-1:-1;32977:42:9;;-1:-1:-1;;;;;32977:4:9;32995:10;32832:55;32977:17;:42::i;:::-;32662:433;32588:507;;;:::o;15714:151::-;10195:17;:15;:17::i;:::-;15791:14:::1;:23:::0;;;15829:29:::1;::::0;1299:25:10;;;15829:29:9::1;::::0;1287:2:10;1272:18;15829:29:9::1;1153:177:10::0;26365:167:9;10591:14;:12;:14::i;:::-;26501:5:::1;::::0;:23:::1;::::0;;-1:-1:-1;;;26501:23:9;;;;26486:39:::1;::::0;-1:-1:-1;;;;;26501:5:9::1;::::0;:21:::1;::::0;:23:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;:5;:23:::1;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;26486:14;:39::i;:::-;26365:167::o:0;30625:1729::-;10591:14;:12;:14::i;:::-;30675::::1;30703:12:::0;30729:23:::1;30755:5;;;;;;;;;-1:-1:-1::0;;;;;30755:5:9::1;-1:-1:-1::0;;;;;30755:21:9::1;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;30825:13;::::0;30729:49;;-1:-1:-1;30788:19:9::1;::::0;30825:13:::1;;30821:559;;;30905:19;30927:23;:21;:23::i;:::-;30905:45;;30982:15;30968:11;:29;30964:216;;;31024:29;31042:11:::0;31024:15;:29:::1;:::i;:::-;31017:36;;30964:216;;;31092:15;31078:11;:29;31074:106;;;31136:29;31150:15:::0;31136:11;:29:::1;:::i;:::-;31127:38;;31074:106;31207:22;31225:4:::0;31207:15;:22:::1;:::i;:::-;31193:36;;30840:400;30821:559;;;31339:30;31353:15;31339:13;:30::i;:::-;31309:60:::0;;-1:-1:-1;31309:60:9;-1:-1:-1;31309:60:9;-1:-1:-1;30821:559:9::1;31459:23;:31:::0;;-1:-1:-1;;31459:31:9::1;::::0;;31505:27:::1;::::0;-1:-1:-1;2274:41:10;;31505:27:9::1;::::0;2262:2:10;2247:18;31505:27:9::1;;;;;;;31744:5;::::0;:31:::1;::::0;-1:-1:-1;;;31744:31:9;;31769:4:::1;31744:31;::::0;::::1;1864:51:10::0;31724:17:9::1;::::0;-1:-1:-1;;;;;31744:5:9::1;::::0;:16:::1;::::0;1837:18:10;;31744:31:9::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;::::0;31813:5:::1;::::0;:39:::1;::::0;-1:-1:-1;;;31813:39:9;;::::1;::::0;::::1;9613:25:10::0;;;9654:18;;;9647:34;;;9697:18;;;9690:34;;;31744:41:9;;-1:-1:-1;;;;;;31813:5:9::1;::::0;:12:::1;::::0;9586:18:10;;31813:39:9::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;31795:57;;31925:31;31940:15;31925:14;:31::i;:::-;32008:13;::::0;::::1;;:42:::0;::::1;;;-1:-1:-1::0;32025:11:9::1;::::0;::::1;::::0;::::1;-1:-1:-1::0;;;;;32025:11:9::1;:25:::0;::::1;32008:42;32004:275;;;32086:11;::::0;32074:85:::1;::::0;-1:-1:-1;;;32074:85:9;;::::1;::::0;::::1;9994:25:10::0;;;10035:18;;;10028:34;;;10078:18;;;10071:34;;;10121:18;;;10114:34;;;10164:19;;;10157:35;;;32086:11:9::1;::::0;;::::1;-1:-1:-1::0;;;;;32086:11:9::1;::::0;32074:30:::1;::::0;9966:19:10;;32074:85:9::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;32066:110;;;::::0;-1:-1:-1;;;32066:110:9;;10655:2:10;32066:110:9::1;::::0;::::1;10637:21:10::0;10694:2;10674:18;;;10667:30;-1:-1:-1;;;10713:18:10;;;10706:42;10765:18;;32066:110:9::1;10453:336:10::0;32066:110:9::1;32004:275;;;32212:22;::::0;32229:4:::1;2274:41:10::0;;32212:22:9::1;::::0;2262:2:10;2247:18;32212:22:9::1;;;;;;;32264:4;32248:20:::0;;-1:-1:-1;;32248:20:9::1;::::0;::::1;::::0;;32004:275:::1;32294:53;::::0;;11025:25:10;;;11081:2;11066:18;;11059:34;;;11109:18;;;11102:34;;;11167:2;11152:18;;11145:34;;;32294:53:9::1;::::0;11012:3:10;10997:19;32294:53:9::1;;;;;;;30665:1689;;;;;30625:1729::o:0;4632:364:8:-;4857:6;;;;;-1:-1:-1;;;;;4857:6:8;4849:29;4841:38;;;;;;4889:51;4901:6;4909:11;4922:8;4932:7;4889:11;:51::i;:::-;4950:39;4966:7;4975:13;4950:15;:39::i;:::-;4632:364;;;;;;:::o;14501:170:9:-;10195:17;:15;:17::i;:::-;-1:-1:-1;;;;;14579:21:9;::::1;14571:30;;;::::0;::::1;;14611:6;:16:::0;;-1:-1:-1;;;;;;14611:16:9::1;-1:-1:-1::0;;;;;14611:16:9;::::1;::::0;;::::1;::::0;;;14642:22:::1;::::0;1864:51:10;;;14642:22:9::1;::::0;1852:2:10;1837:18;14642:22:9::1;1704:217:10::0;18439:168:9;10195:17;:15;:17::i;:::-;18527:11:::1;:26;18541:12:::0;;18527:11;:26:::1;:::i;:::-;;18568:32;18587:12;;18568:32;;;;;;;:::i;:::-;;;;;;;;18439:168:::0;;:::o;3432:1194:8:-;3698:10;;3659:19;;3698:10;;3690:19;;;;;;3961:4;3955:11;-1:-1:-1;;;3979:132:8;;3865:4;3849:22;;4147:4;4131:21;;4124:43;;;-1:-1:-1;;;4220:4:8;4204:21;;4180:143;3849:22;4373:4;3955:11;3826:20;4351:27;4398:186;;-1:-1:-1;;;4398:186:8;;4336:42;;-1:-1:-1;;;;;;4398:40:8;;;-1:-1:-1;4398:40:8;;:186;;4452:6;;4472:11;;4497:8;;4519:7;;4540;;4561:13;;4398:186;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4600:19:8;;-1:-1:-1;;;;;4600:19:8;;;-1:-1:-1;4600:19:8;;-1:-1:-1;4600:19:8;;;3680:946;3432:1194;;;;;;;;:::o;10063:117::-;10668:20:9;:18;:20::i;:::-;10145:28:8::1;10165:7;10145:19;:28::i;:::-;10063:117:::0;:::o;6047:131::-;6130:5;;:31;;-1:-1:-1;;;6130:31:8;;6155:4;6130:31;;;1864:51:10;6104:7:8;;-1:-1:-1;;;;;6130:5:8;;:16;;1837:18:10;;6130:31:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;6123:48;;6047:131;:::o;29645:193:9:-;29717:13;;29697:4;;29717:13;;;-1:-1:-1;;;;;29717:13:9;29713:118;;-1:-1:-1;29753:4:9;;29645:193::o;29713:118::-;29788:13;;;;;;;;;-1:-1:-1;;;;;29788:13:9;-1:-1:-1;;;;;29779:50:9;;:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;17971:175::-;10668:20;:18;:20::i;:::-;18058:13:::1;:30:::0;;-1:-1:-1;;;;;;18058:30:9::1;;-1:-1:-1::0;;;;;18058:30:9;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;18103:36:::1;::::0;1864:51:10;;;18103:36:9::1;::::0;1852:2:10;1837:18;18103:36:9::1;1704:217:10::0;13372:168:9;10668:20;:18;:20::i;:::-;13461:32:::1;::::0;2299:14:10;;2292:22;2274:41;;13461:32:9::1;::::0;2262:2:10;2247:18;13461:32:9::1;;;;;;;13503:13;:30:::0;;-1:-1:-1;;13503:30:9::1;::::0;::::1;;::::0;;;::::1;::::0;;13372:168::o;15845:215:8:-;10668:20:9;:18;:20::i;:::-;15977:5:8::1;15960:14;:22;15952:61;;;::::0;-1:-1:-1;;;15952:61:8;;14512:2:10;15952:61:8::1;::::0;::::1;14494:21:10::0;14551:2;14531:18;;;14524:30;14590:28;14570:18;;;14563:56;14636:18;;15952:61:8::1;14310:350:10::0;15952:61:8::1;16023:13;:30:::0;15845:215::o;14602:475::-;14873:4;;14829:50;;-1:-1:-1;;;14829:50:8;;-1:-1:-1;;;;;14873:4:8;;;14829:50;;;1864:51:10;14656:7:8;;14717:42;;14656:7;;14717:42;;14829:35;;1837:18:10;;14829:50:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14791:88;;15052:6;;;;;;;;;-1:-1:-1;;;;;15052:6:8;-1:-1:-1;;;;;15052:15:8;;:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;15048:21;;:2;:21;:::i;:::-;15028:15;15007:18;:16;:18::i;:::-;:36;;;;:::i;:::-;15006:64;;;;:::i;:::-;14999:71;;;;14602:475;:::o;6241:108::-;6313:4;;:29;;-1:-1:-1;;;6313:29:8;;6336:4;6313:29;;;1864:51:10;6287:7:8;;-1:-1:-1;;;;;6313:4:8;;:14;;1837:18:10;;6313:29:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;13764:198:9:-;10195:17;:15;:17::i;:::-;-1:-1:-1;;;;;13850:25:9;::::1;13842:34;;;::::0;::::1;;13886:10;:24:::0;;-1:-1:-1;;;;;;13886:24:9::1;-1:-1:-1::0;;;;;13886:24:9;::::1;::::0;;::::1;::::0;;;13925:30:::1;::::0;1864:51:10;;;13925:30:9::1;::::0;1852:2:10;1837:18;13925:30:9::1;1704:217:10::0;33846:276:9;33934:5;;-1:-1:-1;;;;;33934:5:9;33912:10;:28;33904:37;;;;;;33997:5;;33959:34;;;-1:-1:-1;;;33959:34:9;;;;-1:-1:-1;;;;;33997:5:9;;;;33959:32;;;;;:34;;;;;;;;;;;;;;:32;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;33959:43:9;;33951:52;;;;;;34013:30;34030:12;34013:16;:30::i;:::-;34085:4;;:29;;-1:-1:-1;;;34085:29:9;;34108:4;34085:29;;;1864:51:10;34053:62:9;;34071:12;;-1:-1:-1;;;;;34085:4:9;;;;:14;;1837:18:10;;34085:29:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;34053:4;;-1:-1:-1;;;;;34053:4:9;;:62;:17;:62::i;14950:261::-;10519:15;:13;:15::i;:::-;-1:-1:-1;;;;;15028:22:9;::::1;15020:31;;;::::0;::::1;;15061:5;::::0;15075:7:::1;::::0;;15061:25:::1;::::0;-1:-1:-1;;;15061:25:9;;-1:-1:-1;;;;;15075:7:9;;::::1;15061:25:::0;;::::1;16889:51:10::0;;;;15061:5:9::1;16956:18:10::0;;;16949:34;15061:5:9;;::::1;::::0;:13:::1;::::0;16862:18:10;;15061:25:9::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;15096:7:9::1;:18:::0;;-1:-1:-1;;;;;;15096:18:9::1;-1:-1:-1::0;;;;;15096:18:9;;::::1;::::0;;::::1;::::0;;15124:5:::1;::::0;:41:::1;::::0;-1:-1:-1;;;15124:41:9;;;;::::1;16889:51:10::0;;;;-1:-1:-1;;16956:18:10;;;16949:34;15124:5:9::1;::::0;:13:::1;::::0;16862:18:10;;15124:41:9::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;15180:24:9::1;::::0;-1:-1:-1;;;;;1882:32:10;;1864:51;;15180:24:9::1;::::0;1852:2:10;1837:18;15180:24:9::1;1704:217:10::0;12779:1553:8;12888:4;13046:10;:8;:10::i;:::-;13041:54;;-1:-1:-1;13079:5:8;;12779:1553;-1:-1:-1;12779:1553:8:o;13041:54::-;13202:23;13228;:21;:23::i;:::-;13202:49;;13283:22;;13265:15;:40;13261:82;;;-1:-1:-1;13328:4:8;;12779:1553;-1:-1:-1;;12779:1553:8:o;13261:82::-;13452:21;:19;:21::i;:::-;13447:65;;-1:-1:-1;13496:5:8;;12779:1553;-1:-1:-1;;12779:1553:8:o;13447:65::-;13617:23;;;;13613:65;;;-1:-1:-1;13663:4:8;;12779:1553;-1:-1:-1;;12779:1553:8:o;13613:65::-;13810:22;;13792:15;:40;13788:82;;;-1:-1:-1;13855:4:8;;12779:1553;-1:-1:-1;;12779:1553:8:o;13788:82::-;13911:5;;:31;;-1:-1:-1;;;13911:31:8;;13936:4;13911:31;;;1864:51:10;13880:28:8;;-1:-1:-1;;;;;13911:5:8;;:16;;1837:18:10;;13911:31:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13880:62;;14061:14;;14041:6;:17;;;14023:15;:35;;;;:::i;:::-;:52;14019:94;;;-1:-1:-1;14098:4:8;;12779:1553;-1:-1:-1;;;12779:1553:8:o;14019:94::-;14211:15;;14185:5;;;;;;;;;-1:-1:-1;;;;;14185:5:8;-1:-1:-1;;;;;14185:21:8;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;14181:83;;;-1:-1:-1;14249:4:8;;12779:1553;-1:-1:-1;;;12779:1553:8:o;14181:83::-;-1:-1:-1;14320:5:8;;12779:1553;-1:-1:-1;;;12779:1553:8:o;16441:271::-;10668:20:9;:18;:20::i;:::-;16599:22:8::1;:48:::0;;;;16657:22:::1;:48:::0;16441:271::o;5546:184::-;5656:7;5704:19;:17;:19::i;:::-;5686:15;:13;:15::i;:::-;:37;;;;:::i;16368:151:9:-;10195:17;:15;:17::i;:::-;16445:14:::1;:23:::0;;;16483:29:::1;::::0;1299:25:10;;;16483:29:9::1;::::0;1287:2:10;1272:18;16483:29:9::1;1153:177:10::0;6448:230:8;6601:6;;6626:31;;-1:-1:-1;;;6626:31:8;;6651:4;6626:31;;;1864:51:10;-1:-1:-1;;1852:42:8;;6544:31;;6601:6;;;-1:-1:-1;;;;;6601:6:8;;;;6626:16;;1837:18:10;;6626:31:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6544:127;;-1:-1:-1;;;;;;6544:127:8;;;;;;;-1:-1:-1;;;;;16907:32:10;;;6544:127:8;;;16889:51:10;16956:18;;;16949:34;16862:18;;6544:127:8;16707:282:10;34539:244:9;10281:26;:24;:26::i;:::-;34610:13:::1;:20:::0;;-1:-1:-1;;34610:20:9::1;34626:4;34610:20;::::0;;34644:5:::1;::::0;:31:::1;::::0;-1:-1:-1;;;34644:31:9;;34669:4:::1;34644:31;::::0;::::1;1864:51:10::0;-1:-1:-1;;;;;34644:5:9;;::::1;::::0;:16:::1;::::0;1837:18:10;;34644:31:9::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;::::0;:46;34640:99:::1;;34706:5;;;;;;;;;-1:-1:-1::0;;;;;34706:5:9::1;-1:-1:-1::0;;;;;34706:20:9::1;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;34640:99;34754:22;::::0;::::1;::::0;;;::::1;34539:244::o:0;16854:187::-;10668:20;:18;:20::i;:::-;16945:15:::1;:34:::0;;;16994:40:::1;::::0;1299:25:10;;;16994:40:9::1;::::0;1287:2:10;1272:18;16994:40:9::1;1153:177:10::0;1475:603:4;1830:10;;;1829:62;;-1:-1:-1;1846:39:4;;-1:-1:-1;;;1846:39:4;;1870:4;1846:39;;;17618:34:10;-1:-1:-1;;;;;17688:15:10;;;17668:18;;;17661:43;1846:15:4;;;;;17553:18:10;;1846:39:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;1829:62;1808:163;;;;-1:-1:-1;;;1808:163:4;;17917:2:10;1808:163:4;;;17899:21:10;17956:2;17936:18;;;17929:30;17995:34;17975:18;;;17968:62;-1:-1:-1;;;18046:18:10;;;18039:52;18108:19;;1808:163:4;17715:418:10;1808:163:4;2008:62;;-1:-1:-1;;;;;16907:32:10;;2008:62:4;;;16889:51:10;16956:18;;;16949:34;;;1981:90:4;;2001:5;;-1:-1:-1;;;2031:22:4;16862:18:10;;2008:62:4;;;;-1:-1:-1;;2008:62:4;;;;;;;;;;;;;;-1:-1:-1;;;;;2008:62:4;-1:-1:-1;;;;;;2008:62:4;;;;;;;;;;1981:19;:90::i;:::-;1475:603;;;:::o;3873:223:5:-;4006:12;4037:52;4059:6;4067:4;4073:1;4076:12;4037:21;:52::i;:::-;4030:59;3873:223;-1:-1:-1;;;;3873:223:5:o;11127:88:9:-;11195:12;:10;:12::i;:::-;-1:-1:-1;;;;;11181:26:9;:10;-1:-1:-1;;;;;11181:26:9;;11173:35;;;;;18755:96;18826:5;;:18;;;-1:-1:-1;;;18826:18:9;;;;18800:7;;-1:-1:-1;;;;;18826:5:9;;:16;;:18;;;;;;;;;;;;;;:5;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;763:205:4:-;902:58;;-1:-1:-1;;;;;16907:32:10;;902:58:4;;;16889:51:10;16956:18;;;16949:34;;;875:86:4;;895:5;;-1:-1:-1;;;925:23:4;16862:18:10;;902:58:4;16707:282:10;11640:127:9;11711:5;;;;;;;;;-1:-1:-1;;;;;11711:5:9;-1:-1:-1;;;;;11711:16:9;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;11697:32:9;:10;-1:-1:-1;;;;;11697:32:9;;:62;;;;11747:12;:10;:12::i;11697:62::-;11689:71;;;;;8854:1007:8;8971:25;8998:13;9027:15;9045;:13;:15::i;:::-;9027:33;;9085:13;9074:7;:24;9070:80;;-1:-1:-1;9122:13:8;;9137:1;;-1:-1:-1;8854:1007:8;-1:-1:-1;8854:1007:8:o;9070:80::-;9225:23;;;9311:31;9225:23;9311:19;:31::i;:::-;9353:17;9373:15;:13;:15::i;:::-;9353:35;;9588:9;9572:13;:25;9568:287;;;9613:12;9628:25;9644:9;9628:13;:25;:::i;:::-;9613:40;;9687:9;9667:29;;9721:13;;9714:4;:20;9710:71;;;9762:4;9754:12;;9710:71;9599:192;9568:287;;;9831:13;9811:33;;9568:287;9017:844;;;8854:1007;;;:::o;10712:116:9:-;10780:10;;-1:-1:-1;;;;;10780:10:9;10766;:24;;:54;;;10808:12;:10;:12::i;11341:293::-;11419:6;;-1:-1:-1;;;;;11419:6:9;11405:10;:20;;:64;;-1:-1:-1;11459:10:9;;-1:-1:-1;;;;;11459:10:9;11445;:24;11405:64;:110;;;;11503:12;:10;:12::i;:::-;-1:-1:-1;;;;;11489:26:9;:10;-1:-1:-1;;;;;11489:26:9;;11405:110;:160;;;;11549:5;;;;;;;;;-1:-1:-1;;;;;11549:5:9;-1:-1:-1;;;;;11549:14:9;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;11535:30:9;:10;-1:-1:-1;;;;;11535:30:9;;11405:160;:212;;;;11599:5;;;;;;;;;-1:-1:-1;;;;;11599:5:9;-1:-1:-1;;;;;11599:16:9;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;8497:351:8:-;8615:13;;;;8611:50;;;8497:351;:::o;8611:50::-;8671:15;8689;:13;:15::i;:::-;8671:33;-1:-1:-1;8718:11:8;;8714:128;;8769:6;;8786:4;;8745:56;;-1:-1:-1;;;;;8769:6:8;;;;;;;8786:4;8793:7;8745:15;:56::i;:::-;8815:6;;;;;;;;;-1:-1:-1;;;;;8815:6:8;-1:-1:-1;;;;;8815:14:8;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10699:445;10919:6;;:31;;-1:-1:-1;;;10919:31:8;;10944:4;10919:31;;;1864:51:10;10799:20:8;;;;10919:6;;;;-1:-1:-1;;;;;10919:6:8;;:16;;1837:18:10;;10919:31:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;10891:59;-1:-1:-1;10964:21:8;;10960:110;;11001:6;;11051:7;;11001:58;;-1:-1:-1;;;11001:58:8;;;;;18596:25:10;;;11044:4:8;18637:18:10;;;18630:60;18706:18;;;18699:34;;;;11001:6:8;;;;-1:-1:-1;;;;;11001:6:8;;:15;;18569:18:10;;11001:58:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;10960:110;11122:15;:13;:15::i;:::-;11115:22;;;10699:445;:::o;7143:1348::-;7272:15;7301:13;7328:20;7461:14;7478:22;:20;:22::i;:::-;7461:39;;7510:12;7525:17;:15;:17::i;:::-;7510:32;;7637:4;7627:6;:14;7623:862;;7695:13;;;;-1:-1:-1;7751:16:8;;-1:-1:-1;7782:14:8;7799:22;7751:16;7695:13;7799:22;:::i;:::-;7782:39;;7891:13;7910:25;7928:6;7910:17;:25::i;:::-;7890:45;;;7963:5;7954:6;:14;7950:308;;;8008:5;7992:12;:21;7988:256;;8052:5;8037:20;;8089:1;8079:11;;7988:256;;;8191:12;8183:5;:20;8173:30;;7988:256;7643:625;;7623:862;;;8454:6;8447:4;:13;8439:21;;7623:862;7363:1128;;7143:1348;;;;;:::o;12423:778:9:-;12589:4;;-1:-1:-1;;;;;12589:4:9;12581:27;12573:68;;;;-1:-1:-1;;;12573:68:9;;18946:2:10;12573:68:9;;;18928:21:10;18985:2;18965:18;;;18958:30;19024;19004:18;;;18997:58;19072:18;;12573:68:9;18744:352:10;12573:68:9;12652:5;:24;;-1:-1:-1;;;;;;12652:24:9;-1:-1:-1;;;;;12652:24:9;;;;;;;;12700:13;;;-1:-1:-1;;;12700:13:9;;;;:11;;:13;;;;;;;;;;;;;;;12652:24;12700:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12686:4;:28;;-1:-1:-1;;;;;;12686:28:9;-1:-1:-1;;;;;12686:28:9;;;;;;;;;12724:43;;12741:6;-1:-1:-1;;12724:16:9;:43::i;:::-;12825:10;:24;;-1:-1:-1;;;;;12825:24:9;;;-1:-1:-1;;;;;;12825:24:9;;;;;;;12859:7;:18;;;;;;;;;;;12887:6;:16;;;;;;;;;;;;;;12963:7;12946:14;:24;13014:5;;:16;;;-1:-1:-1;;;13014:16:9;;;;:5;;;;;:14;;:16;;;;;;;;;;;;;;:5;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13010:20;;:2;:20;:::i;:::-;12998:32;;:9;:32;:::i;:::-;12980:15;:50;13123:5;;13137:7;;;13123:41;;-1:-1:-1;;;13123:41:9;;-1:-1:-1;;;;;13137:7:9;;;13123:41;;;16889:51:10;;;;-1:-1:-1;;16956:18:10;;;16949:34;13123:5:9;;;;:13;;16862:18:10;;13123:41:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;12423:778;;;;:::o;5002:284:8:-;5104:6;:24;;-1:-1:-1;;;;;;5104:24:8;;-1:-1:-1;;;;;5104:24:8;;;;;;5138:12;:28;5153:13;5138:12;:28;:::i;:::-;-1:-1:-1;;5201:7:8;5176:22;:32;-1:-1:-1;5243:8:8;5218:22;:33;5277:2;5261:13;:18;5002:284::o;10186:507::-;10255:7;10266:1;10255:12;10251:49;;10186:507;:::o;10251:49::-;10338:6;;:31;;-1:-1:-1;;;10338:31:8;;10363:4;10338:31;;;1864:51:10;10310:25:8;;10338:6;;;-1:-1:-1;;;;;10338:6:8;;:16;;1837:18:10;;10338:31:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;10484:6;;10444:57;;-1:-1:-1;;;10444:57:8;;10484:6;;;;-1:-1:-1;;;;;10484:6:8;10444:57;;;16889:51:10;16956:18;;;16949:34;;;10310:59:8;;-1:-1:-1;;;10418:132:8;;1852:42;;10444:31;;16862:18:10;;10444:57:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;10519:17;10418:8;:132::i;:::-;10379:171;;10565:16;10585:1;10565:21;10561:58;;10602:7;;10186:507;:::o;10561:58::-;10629:6;;10678:7;;10629:57;;-1:-1:-1;;;10629:57:8;;;;;18596:25:10;;;10671:4:8;18637:18:10;;;18630:60;18706:18;;;18699:34;;;;10629:6:8;;;;-1:-1:-1;;;;;10629:6:8;;:15;;18569:18:10;;10629:57:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;10241:452;;10186:507;:::o;11150:207::-;11308:6;;11301:39;;-1:-1:-1;;;11301:39:8;;11334:4;11301:39;;;1864:51:10;11234:116:8;;11275:12;;11308:6;;;;-1:-1:-1;;;;;11308:6:8;;11301:24;;1837:18:10;;11301:39:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;11241:6;;;;;-1:-1:-1;;;;;11241:6:8;;;11234:27;:116::i;11221:114:9:-;11287:12;:10;:12::i;:::-;-1:-1:-1;;;;;11273:26:9;:10;-1:-1:-1;;;;;11273:26:9;;:54;;;-1:-1:-1;11317:10:9;;-1:-1:-1;;;;;11317:10:9;11303;:24;11265:63;;;;;10834:195;10911:10;;-1:-1:-1;;;;;10911:10:9;10897;:24;;:54;;;10939:12;:10;:12::i;3747:706:4:-;4166:23;4192:69;4220:4;4192:69;;;;;;;;;;;;;;;;;4200:5;-1:-1:-1;;;;;4192:27:4;;;:69;;;;;:::i;:::-;4275:17;;4166:95;;-1:-1:-1;4275:21:4;4271:176;;4370:10;4359:30;;;;;;;;;;;;:::i;:::-;4351:85;;;;-1:-1:-1;;;4351:85:4;;20660:2:10;4351:85:4;;;20642:21:10;20699:2;20679:18;;;20672:30;20738:34;20718:18;;;20711:62;-1:-1:-1;;;20789:18:10;;;20782:40;20839:19;;4351:85:4;20458:406:10;4960:446:5;5125:12;5182:5;5157:21;:30;;5149:81;;;;-1:-1:-1;;;5149:81:5;;21071:2:10;5149:81:5;;;21053:21:10;21110:2;21090:18;;;21083:30;21149:34;21129:18;;;21122:62;-1:-1:-1;;;21200:18:10;;;21193:36;21246:19;;5149:81:5;20869:402:10;5149:81:5;5241:12;5255:23;5282:6;-1:-1:-1;;;;;5282:11:5;5301:5;5308:4;5282:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5240:73;;;;5330:69;5357:6;5365:7;5374:10;5386:12;5330:26;:69::i;:::-;5323:76;4960:446;-1:-1:-1;;;;;;;4960:446:5:o;11488:333:8:-;11618:50;;-1:-1:-1;;;11618:50:8;;11651:4;11618:50;;;17618:34:10;-1:-1:-1;;;;;17688:15:10;;;17668:18;;;17661:43;11671:7:8;;11618:24;;;;;;17553:18:10;;11618:50:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:60;11614:201;;;11694:40;-1:-1:-1;;;;;11694:26:8;;11721:9;11732:1;11694:26;:40::i;:::-;11748:56;-1:-1:-1;;;;;11748:26:8;;11775:9;-1:-1:-1;;11748:26:8;:56::i;588:104:7:-;646:7;676:1;672;:5;:13;;684:1;672:13;;;680:1;672:13;665:20;;588:104;;;;;:::o;7466:628:5:-;7646:12;7674:7;7670:418;;;7701:10;:17;7722:1;7701:22;7697:286;;-1:-1:-1;;;;;1465:19:5;;;7908:60;;;;-1:-1:-1;;;7908:60:5;;21757:2:10;7908:60:5;;;21739:21:10;21796:2;21776:18;;;21769:30;21835:31;21815:18;;;21808:59;21884:18;;7908:60:5;21555:353:10;7908:60:5;-1:-1:-1;8003:10:5;7996:17;;7670:418;8044:33;8052:10;8064:12;8775:17;;:21;8771:379;;9003:10;8997:17;9059:15;9046:10;9042:2;9038:19;9031:44;8771:379;9126:12;9119:20;;-1:-1:-1;;;9119:20:5;;;;;;;;:::i;14:131:10:-;-1:-1:-1;;;;;89:31:10;;79:42;;69:70;;135:1;132;125:12;150:247;209:6;262:2;250:9;241:7;237:23;233:32;230:52;;;278:1;275;268:12;230:52;317:9;304:23;336:31;361:5;336:31;:::i;:::-;386:5;150:247;-1:-1:-1;;;150:247:10:o;402:258::-;474:1;484:113;498:6;495:1;492:13;484:113;;;574:11;;;568:18;555:11;;;548:39;520:2;513:10;484:113;;;615:6;612:1;609:13;606:48;;;-1:-1:-1;;650:1:10;632:16;;625:27;402:258::o;665:::-;707:3;745:5;739:12;772:6;767:3;760:19;788:63;844:6;837:4;832:3;828:14;821:4;814:5;810:16;788:63;:::i;:::-;905:2;884:15;-1:-1:-1;;880:29:10;871:39;;;;912:4;867:50;;665:258;-1:-1:-1;;665:258:10:o;928:220::-;1077:2;1066:9;1059:21;1040:4;1097:45;1138:2;1127:9;1123:18;1115:6;1097:45;:::i;1335:118::-;1421:5;1414:13;1407:21;1400:5;1397:32;1387:60;;1443:1;1440;1433:12;1458:241;1514:6;1567:2;1555:9;1546:7;1542:23;1538:32;1535:52;;;1583:1;1580;1573:12;1535:52;1622:9;1609:23;1641:28;1663:5;1641:28;:::i;2326:180::-;2385:6;2438:2;2426:9;2417:7;2413:23;2409:32;2406:52;;;2454:1;2451;2444:12;2406:52;-1:-1:-1;2477:23:10;;2326:180;-1:-1:-1;2326:180:10:o;2734:127::-;2795:10;2790:3;2786:20;2783:1;2776:31;2826:4;2823:1;2816:15;2850:4;2847:1;2840:15;2866:252;2938:2;2932:9;2980:3;2968:16;;3014:18;2999:34;;3035:22;;;2996:62;2993:88;;;3061:18;;:::i;:::-;3097:2;3090:22;2866:252;:::o;3123:275::-;3194:2;3188:9;3259:2;3240:13;;-1:-1:-1;;3236:27:10;3224:40;;3294:18;3279:34;;3315:22;;;3276:62;3273:88;;;3341:18;;:::i;:::-;3377:2;3370:22;3123:275;;-1:-1:-1;3123:275:10:o;3403:1466::-;3517:6;3525;3533;3541;3549;3557;3610:3;3598:9;3589:7;3585:23;3581:33;3578:53;;;3627:1;3624;3617:12;3578:53;3666:9;3653:23;3685:31;3710:5;3685:31;:::i;:::-;3735:5;-1:-1:-1;3759:2:10;3798:18;;;3785:32;3826:33;3785:32;3826:33;:::i;:::-;3878:7;-1:-1:-1;3937:2:10;3922:18;;3909:32;3950:33;3909:32;3950:33;:::i;:::-;4002:7;-1:-1:-1;4061:2:10;4046:18;;4033:32;4074:33;4033:32;4074:33;:::i;:::-;4126:7;-1:-1:-1;4185:3:10;4170:19;;4157:33;4199;4157;4199;:::i;:::-;4251:7;-1:-1:-1;4309:3:10;4294:19;;4281:33;4333:18;4363:14;;;4360:34;;;4390:1;4387;4380:12;4360:34;4428:6;4417:9;4413:22;4403:32;;4473:7;4466:4;4462:2;4458:13;4454:27;4444:55;;4495:1;4492;4485:12;4444:55;4531:2;4518:16;4553:2;4549;4546:10;4543:36;;;4559:18;;:::i;:::-;4601:53;4644:2;4625:13;;-1:-1:-1;;4621:27:10;4617:36;;4601:53;:::i;:::-;4588:66;;4677:2;4670:5;4663:17;4717:7;4712:2;4707;4703;4699:11;4695:20;4692:33;4689:53;;;4738:1;4735;4728:12;4689:53;4793:2;4788;4784;4780:11;4775:2;4768:5;4764:14;4751:45;4837:1;4832:2;4827;4820:5;4816:14;4812:23;4805:34;;4858:5;4848:15;;;;;3403:1466;;;;;;;;:::o;4874:592::-;4945:6;4953;5006:2;4994:9;4985:7;4981:23;4977:32;4974:52;;;5022:1;5019;5012:12;4974:52;5062:9;5049:23;5091:18;5132:2;5124:6;5121:14;5118:34;;;5148:1;5145;5138:12;5118:34;5186:6;5175:9;5171:22;5161:32;;5231:7;5224:4;5220:2;5216:13;5212:27;5202:55;;5253:1;5250;5243:12;5202:55;5293:2;5280:16;5319:2;5311:6;5308:14;5305:34;;;5335:1;5332;5325:12;5305:34;5380:7;5375:2;5366:6;5362:2;5358:15;5354:24;5351:37;5348:57;;;5401:1;5398;5391:12;5348:57;5432:2;5424:11;;;;;5454:6;;-1:-1:-1;4874:592:10;;-1:-1:-1;;;;4874:592:10:o;5695:248::-;5763:6;5771;5824:2;5812:9;5803:7;5799:23;5795:32;5792:52;;;5840:1;5837;5830:12;5792:52;-1:-1:-1;;5863:23:10;;;5933:2;5918:18;;;5905:32;;-1:-1:-1;5695:248:10:o;6841:127::-;6902:10;6897:3;6893:20;6890:1;6883:31;6933:4;6930:1;6923:15;6957:4;6954:1;6947:15;7312:127;7373:10;7368:3;7364:20;7361:1;7354:31;7404:4;7401:1;7394:15;7428:4;7425:1;7418:15;7444:135;7483:3;7504:17;;;7501:43;;7524:18;;:::i;:::-;-1:-1:-1;7571:1:10;7560:13;;7444:135::o;7584:184::-;7654:6;7707:2;7695:9;7686:7;7682:23;7678:32;7675:52;;;7723:1;7720;7713:12;7675:52;-1:-1:-1;7746:16:10;;7584:184;-1:-1:-1;7584:184:10:o;7773:380::-;7852:1;7848:12;;;;7895;;;7916:61;;7970:4;7962:6;7958:17;7948:27;;7916:61;8023:2;8015:6;8012:14;7992:18;7989:38;7986:161;;8069:10;8064:3;8060:20;8057:1;8050:31;8104:4;8101:1;8094:15;8132:4;8129:1;8122:15;8158:784;8260:6;8313:3;8301:9;8292:7;8288:23;8284:33;8281:53;;;8330:1;8327;8320:12;8281:53;8356:22;;:::i;:::-;8407:9;8401:16;8394:5;8387:31;8471:2;8460:9;8456:18;8450:25;8445:2;8438:5;8434:14;8427:49;8529:2;8518:9;8514:18;8508:25;8503:2;8496:5;8492:14;8485:49;8587:2;8576:9;8572:18;8566:25;8561:2;8554:5;8550:14;8543:49;8646:3;8635:9;8631:19;8625:26;8619:3;8612:5;8608:15;8601:51;8706:3;8695:9;8691:19;8685:26;8679:3;8672:5;8668:15;8661:51;8766:3;8755:9;8751:19;8745:26;8739:3;8732:5;8728:15;8721:51;8826:3;8815:9;8811:19;8805:26;8799:3;8792:5;8788:15;8781:51;8851:3;8907:2;8896:9;8892:18;8886:25;8881:2;8874:5;8870:14;8863:49;;8931:5;8921:15;;;8158:784;;;;:::o;9281:125::-;9321:4;9349:1;9346;9343:8;9340:34;;;9354:18;;:::i;:::-;-1:-1:-1;9391:9:10;;9281:125::o;10203:245::-;10270:6;10323:2;10311:9;10302:7;10298:23;10294:32;10291:52;;;10339:1;10336;10329:12;10291:52;10371:9;10365:16;10390:28;10412:5;10390:28;:::i;11316:545::-;11418:2;11413:3;11410:11;11407:448;;;11454:1;11479:5;11475:2;11468:17;11524:4;11520:2;11510:19;11594:2;11582:10;11578:19;11575:1;11571:27;11565:4;11561:38;11630:4;11618:10;11615:20;11612:47;;;-1:-1:-1;11653:4:10;11612:47;11708:2;11703:3;11699:12;11696:1;11692:20;11686:4;11682:31;11672:41;;11763:82;11781:2;11774:5;11771:13;11763:82;;;11826:17;;;11807:1;11796:13;11763:82;;12037:1206;12161:18;12156:3;12153:27;12150:53;;;12183:18;;:::i;:::-;12212:94;12302:3;12262:38;12294:4;12288:11;12262:38;:::i;:::-;12256:4;12212:94;:::i;:::-;12332:1;12357:2;12352:3;12349:11;12374:1;12369:616;;;;13029:1;13046:3;13043:93;;;-1:-1:-1;13102:19:10;;;13089:33;13043:93;-1:-1:-1;;11994:1:10;11990:11;;;11986:24;11982:29;11972:40;12018:1;12014:11;;;11969:57;13149:78;;12342:895;;12369:616;11263:1;11256:14;;;11300:4;11287:18;;-1:-1:-1;;12405:17:10;;;12506:9;12528:229;12542:7;12539:1;12536:14;12528:229;;;12631:19;;;12618:33;12603:49;;12738:4;12723:20;;;;12691:1;12679:14;;;;12558:12;12528:229;;;12532:3;12785;12776:7;12773:16;12770:159;;;12909:1;12905:6;12899:3;12893;12890:1;12886:11;12882:21;12878:34;12874:39;12861:9;12856:3;12852:19;12839:33;12835:79;12827:6;12820:95;12770:159;;;12972:1;12966:3;12963:1;12959:11;12955:19;12949:4;12942:33;12342:895;;12037:1206;;;:::o;13248:390::-;13407:2;13396:9;13389:21;13446:6;13441:2;13430:9;13426:18;13419:34;13503:6;13495;13490:2;13479:9;13475:18;13462:48;13559:1;13530:22;;;13554:2;13526:31;;;13519:42;;;;13622:2;13601:15;;;-1:-1:-1;;13597:29:10;13582:45;13578:54;;13248:390;-1:-1:-1;13248:390:10:o;13643:662::-;-1:-1:-1;;;;;13970:15:10;;;13952:34;;14022:15;;;14017:2;14002:18;;13995:43;14074:15;;;14069:2;14054:18;;14047:43;14126:15;;;14121:2;14106:18;;14099:43;14179:15;;14173:3;14158:19;;14151:44;14232:3;13932;14211:19;;14204:32;;;13895:4;;14253:46;;14279:19;;14271:6;14253:46;:::i;:::-;14245:54;13643:662;-1:-1:-1;;;;;;;;13643:662:10:o;14665:422::-;14754:1;14797:5;14754:1;14811:270;14832:7;14822:8;14819:21;14811:270;;;14891:4;14887:1;14883:6;14879:17;14873:4;14870:27;14867:53;;;14900:18;;:::i;:::-;14950:7;14940:8;14936:22;14933:55;;;14970:16;;;;14933:55;15049:22;;;;15009:15;;;;14811:270;;;14815:3;14665:422;;;;;:::o;15092:806::-;15141:5;15171:8;15161:80;;-1:-1:-1;15212:1:10;15226:5;;15161:80;15260:4;15250:76;;-1:-1:-1;15297:1:10;15311:5;;15250:76;15342:4;15360:1;15355:59;;;;15428:1;15423:130;;;;15335:218;;15355:59;15385:1;15376:10;;15399:5;;;15423:130;15460:3;15450:8;15447:17;15444:43;;;15467:18;;:::i;:::-;-1:-1:-1;;15523:1:10;15509:16;;15538:5;;15335:218;;15637:2;15627:8;15624:16;15618:3;15612:4;15609:13;15605:36;15599:2;15589:8;15586:16;15581:2;15575:4;15572:12;15568:35;15565:77;15562:159;;;-1:-1:-1;15674:19:10;;;15706:5;;15562:159;15753:34;15778:8;15772:4;15753:34;:::i;:::-;15823:6;15819:1;15815:6;15811:19;15802:7;15799:32;15796:58;;;15834:18;;:::i;:::-;15872:20;;15092:806;-1:-1:-1;;;15092:806:10:o;15903:131::-;15963:5;15992:36;16019:8;16013:4;15992:36;:::i;16039:168::-;16079:7;16145:1;16141;16137:6;16133:14;16130:1;16127:21;16122:1;16115:9;16108:17;16104:45;16101:71;;;16152:18;;:::i;:::-;-1:-1:-1;16192:9:10;;16039:168::o;16212:217::-;16252:1;16278;16268:132;;16322:10;16317:3;16313:20;16310:1;16303:31;16357:4;16354:1;16347:15;16385:4;16382:1;16375:15;16268:132;-1:-1:-1;16414:9:10;;16212:217::o;16434:268::-;16521:6;16574:2;16562:9;16553:7;16549:23;16545:32;16542:52;;;16590:1;16587;16580:12;16542:52;16622:9;16616:16;16641:31;16666:5;16641:31;:::i;17273:128::-;17313:3;17344:1;17340:6;17337:1;17334:13;17331:39;;;17350:18;;:::i;:::-;-1:-1:-1;17386:9:10;;17273:128::o;19101:1352::-;19227:3;19221:10;19254:18;19246:6;19243:30;19240:56;;;19276:18;;:::i;:::-;19305:97;19395:6;19355:38;19387:4;19381:11;19355:38;:::i;:::-;19349:4;19305:97;:::i;:::-;19457:4;;19521:2;19510:14;;19538:1;19533:663;;;;20240:1;20257:6;20254:89;;;-1:-1:-1;20309:19:10;;;20303:26;20254:89;-1:-1:-1;;11994:1:10;11990:11;;;11986:24;11982:29;11972:40;12018:1;12014:11;;;11969:57;20356:81;;19503:944;;19533:663;11263:1;11256:14;;;11300:4;11287:18;;-1:-1:-1;;19569:20:10;;;19687:236;19701:7;19698:1;19695:14;19687:236;;;19790:19;;;19784:26;19769:42;;19882:27;;;;19850:1;19838:14;;;;19717:19;;19687:236;;;19691:3;19951:6;19942:7;19939:19;19936:201;;;20012:19;;;20006:26;-1:-1:-1;;20095:1:10;20091:14;;;20107:3;20087:24;20083:37;20079:42;20064:58;20049:74;;19936:201;-1:-1:-1;;;;;20183:1:10;20167:14;;;20163:22;20150:36;;-1:-1:-1;19101:1352:10:o;21276:274::-;21405:3;21443:6;21437:13;21459:53;21505:6;21500:3;21493:4;21485:6;21481:17;21459:53;:::i;:::-;21528:16;;;;;21276:274;-1:-1:-1;;21276:274:10:o
Swarm Source
ipfs://36aa1d7c57341d491068eb52b81162d96db22a453d81893d0bf4e46d97791246
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.