Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 5 from a total of 5 transactions
Latest 2 internal transactions
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x3d602d80 | 20671872 | 536 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 20491947 | 561 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:
V3Router
Compiler Version
v0.8.18+commit.87f61d96
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.15;
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
// V3 vault and strategy use the same relevant interface.
import {IVault} from "./interfaces/IVault.sol";
// These are the core Yearn libraries
import {BaseStrategyInitializable, StrategyParams, SafeERC20, IERC20} from "https://github.com/yearn/yearn-vaults/blob/master/contracts//BaseStrategy.sol";
contract V3Router is BaseStrategyInitializable {
using SafeERC20 for IERC20;
// V3 vault to use.
IVault public v3Vault;
// Max loss for withdraws.
uint256 public maxLoss;
// Strategy specific name.
string internal _name;
constructor(
address _vault,
address _v3Vault,
string memory name_
) BaseStrategyInitializable(_vault) {
initializeThis(_v3Vault, name_);
}
function cloneV3Router(
address _vault,
address _v3Vault,
string memory name_,
address _strategist,
address _rewards,
address _keeper
) external returns (address _newV3Router) {
_newV3Router = clone(_vault, _strategist, _rewards, _keeper);
V3Router(_newV3Router).initializeThis(_v3Vault, name_);
}
function initializeThis(address _v3Vault, string memory name_) public {
require(address(v3Vault) == address(0), "!initialized");
require(IVault(_v3Vault).asset() == address(want), "wrong want");
want.safeApprove(_v3Vault, type(uint256).max);
v3Vault = IVault(_v3Vault);
// Default to 1bps max loss
maxLoss = 1;
_name = name_;
// Set health check
healthCheck = 0xDDCea799fF1699e98EDF118e0629A974Df7DF012;
}
// ******** OVERRIDE THESE METHODS FROM BASE CONTRACT ************
function name() external view override returns (string memory) {
return _name;
}
function estimatedTotalAssets() public view override returns (uint256) {
return balanceOfWant() + balanceOfVault();
}
function balanceOfWant() public view returns (uint256) {
return want.balanceOf(address(this));
}
function balanceOfVault() public view returns (uint256) {
return v3Vault.convertToAssets(v3Vault.balanceOf(address(this)));
}
function prepareReturn(
uint256 _debtOutstanding
)
internal
override
returns (uint256 _profit, uint256 _loss, uint256 _debtPayment)
{
uint256 totalAssets = estimatedTotalAssets();
uint256 totalDebt = vault.strategies(address(this)).totalDebt;
if (totalDebt < totalAssets) {
// we have profit
unchecked {
_profit = totalAssets - totalDebt;
}
} else {
// we have losses
unchecked {
_loss = totalDebt - totalAssets;
}
}
(uint256 _amountFreed, uint256 _lost) = liquidatePosition(
_debtOutstanding + _profit
);
if (_loss > 0) {
// Add any more lost on the withdraw
_loss += _lost;
_debtPayment = _amountFreed;
} else {
if (_lost > _profit) {
// Loss negates all profits.
_profit = 0;
unchecked {
_loss = _lost - _profit;
}
_debtPayment = _amountFreed;
} else {
unchecked {
_profit -= _lost;
}
_debtPayment = _debtOutstanding;
}
}
}
function adjustPosition(uint256) internal override {
uint256 toDeploy = Math.min(
balanceOfWant(),
v3Vault.maxDeposit(address(this))
);
if (toDeploy > 0) {
v3Vault.deposit(toDeploy, address(this));
}
}
function liquidatePosition(
uint256 _amountNeeded
) internal override returns (uint256 _liquidatedAmount, uint256 _loss) {
uint256 balance = balanceOfWant();
if (_amountNeeded > balance) {
// Adjust the amount down based on the maxRedeem.
_amountNeeded = Math.min(
_amountNeeded,
balance +
v3Vault.convertToAssets(v3Vault.maxRedeem(address(this)))
);
// Check if we still have something to withdraw.
if (_amountNeeded > balance) {
v3Vault.redeem(
v3Vault.convertToShares(_amountNeeded - balance),
address(this),
address(this),
maxLoss
);
}
}
balance = balanceOfWant();
if (_amountNeeded > balance) {
_liquidatedAmount = balance;
unchecked {
_loss = _amountNeeded - balance;
}
} else {
_liquidatedAmount = _amountNeeded;
}
}
function liquidateAllPositions() internal override returns (uint256) {
v3Vault.redeem(
v3Vault.balanceOf(address(this)),
address(this),
address(this),
maxLoss
);
return balanceOfWant();
}
function prepareMigration(address _newStrategy) internal override {
uint256 balance = v3Vault.balanceOf(address(this));
if (balance > 0) {
v3Vault.transfer(_newStrategy, balance);
}
}
function setMaxLoss(uint256 _newMaxLoss) external onlyAuthorized {
require(_newMaxLoss <= 10_000, "too high");
maxLoss = _newMaxLoss;
}
function protectedTokens()
internal
view
override
returns (address[] memory)
{}
function ethToWant(
uint256 _amtInWei
) public view virtual override returns (uint256) {
return _amtInWei;
}
}// 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: GPL-3.0
pragma solidity >=0.8.18;
import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol";
interface IVault is IERC4626 {
// STRATEGY EVENTS
event StrategyChanged(address indexed strategy, uint256 change_type);
event StrategyReported(
address indexed strategy,
uint256 gain,
uint256 loss,
uint256 current_debt,
uint256 protocol_fees,
uint256 total_fees,
uint256 total_refunds
);
// DEBT MANAGEMENT EVENTS
event DebtUpdated(
address indexed strategy,
uint256 current_debt,
uint256 new_debt
);
// ROLE UPDATES
event RoleSet(address indexed account, uint256 role);
event UpdateRoleManager(address indexed role_manager);
event UpdateAccountant(address indexed accountant);
event UpdateDefaultQueue(address[] new_default_queue);
event UpdateUseDefaultQueue(bool use_default_queue);
event UpdatedMaxDebtForStrategy(
address indexed sender,
address indexed strategy,
uint256 new_debt
);
event UpdateDepositLimit(uint256 deposit_limit);
event UpdateMinimumTotalIdle(uint256 minimum_total_idle);
event UpdateProfitMaxUnlockTime(uint256 profit_max_unlock_time);
event DebtPurchased(address indexed strategy, uint256 amount);
event Shutdown();
struct StrategyParams {
uint256 activation;
uint256 last_report;
uint256 current_debt;
uint256 max_debt;
}
function FACTORY() external view returns (uint256);
function strategies(address) external view returns (StrategyParams memory);
function default_queue(uint256) external view returns (address);
function use_default_queue() external view returns (bool);
function minimum_total_idle() external view returns (uint256);
function deposit_limit() external view returns (uint256);
function deposit_limit_module() external view returns (address);
function withdraw_limit_module() external view returns (address);
function accountant() external view returns (address);
function roles(address) external view returns (uint256);
function role_manager() external view returns (address);
function future_role_manager() external view returns (address);
function isShutdown() external view returns (bool);
function nonces(address) external view returns (uint256);
function initialize(
address,
string memory,
string memory,
address,
uint256
) external;
function set_accountant(address new_accountant) external;
function set_default_queue(address[] memory new_default_queue) external;
function set_use_default_queue(bool) external;
function set_deposit_limit(uint256 deposit_limit) external;
function set_deposit_limit(
uint256 deposit_limit,
bool should_override
) external;
function set_deposit_limit_module(
address new_deposit_limit_module
) external;
function set_deposit_limit_module(
address new_deposit_limit_module,
bool should_override
) external;
function set_withdraw_limit_module(
address new_withdraw_limit_module
) external;
function set_minimum_total_idle(uint256 minimum_total_idle) external;
function setProfitMaxUnlockTime(
uint256 new_profit_max_unlock_time
) external;
function set_role(address account, uint256 role) external;
function add_role(address account, uint256 role) external;
function remove_role(address account, uint256 role) external;
function transfer_role_manager(address role_manager) external;
function accept_role_manager() external;
function unlockedShares() external view returns (uint256);
function pricePerShare() external view returns (uint256);
function get_default_queue() external view returns (address[] memory);
function process_report(
address strategy
) external returns (uint256, uint256);
function buy_debt(address strategy, uint256 amount) external;
function add_strategy(address new_strategy) external;
function revoke_strategy(address strategy) external;
function force_revoke_strategy(address strategy) external;
function update_max_debt_for_strategy(
address strategy,
uint256 new_max_debt
) external;
function update_debt(
address strategy,
uint256 target_debt
) external returns (uint256);
function update_debt(
address strategy,
uint256 target_debt,
uint256 max_loss
) external returns (uint256);
function shutdown_vault() external;
function totalIdle() external view returns (uint256);
function totalDebt() external view returns (uint256);
function apiVersion() external view returns (string memory);
function assess_share_of_unrealised_losses(
address strategy,
uint256 assets_needed
) external view returns (uint256);
function profitMaxUnlockTime() external view returns (uint256);
function fullProfitUnlockDate() external view returns (uint256);
function profitUnlockingRate() external view returns (uint256);
function lastProfitUpdate() external view returns (uint256);
//// NON-STANDARD ERC-4626 FUNCTIONS \\\\
function withdraw(
uint256 assets,
address receiver,
address owner,
uint256 max_loss
) external returns (uint256);
function withdraw(
uint256 assets,
address receiver,
address owner,
uint256 max_loss,
address[] memory strategies
) external returns (uint256);
function redeem(
uint256 shares,
address receiver,
address owner,
uint256 max_loss
) external returns (uint256);
function redeem(
uint256 shares,
address receiver,
address owner,
uint256 max_loss,
address[] memory strategies
) external returns (uint256);
function maxWithdraw(
address owner,
uint256 max_loss
) external view returns (uint256);
function maxWithdraw(
address owner,
uint256 max_loss,
address[] memory strategies
) external view returns (uint256);
function maxRedeem(
address owner,
uint256 max_loss
) external view returns (uint256);
function maxRedeem(
address owner,
uint256 max_loss,
address[] memory strategies
) external view returns (uint256);
//// NON-STANDARD ERC-20 FUNCTIONS \\\\
function DOMAIN_SEPARATOR() external view returns (bytes32);
function permit(
address owner,
address spender,
uint256 amount,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external returns (bool);
}// 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: 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) (interfaces/IERC4626.sol)
pragma solidity ^0.8.0;
import "../token/ERC20/IERC20.sol";
import "../token/ERC20/extensions/IERC20Metadata.sol";
/**
* @dev Interface of the ERC4626 "Tokenized Vault Standard", as defined in
* https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].
*
* _Available since v4.7._
*/
interface IERC4626 is IERC20, IERC20Metadata {
event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed sender,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
/**
* @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
*
* - MUST be an ERC-20 token contract.
* - MUST NOT revert.
*/
function asset() external view returns (address assetTokenAddress);
/**
* @dev Returns the total amount of the underlying asset that is “managed” by Vault.
*
* - SHOULD include any compounding that occurs from yield.
* - MUST be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT revert.
*/
function totalAssets() external view returns (uint256 totalManagedAssets);
/**
* @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToShares(uint256 assets) external view returns (uint256 shares);
/**
* @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToAssets(uint256 shares) external view returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
* through a deposit call.
*
* - MUST return a limited value if receiver is subject to some deposit limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
* - MUST NOT revert.
*/
function maxDeposit(address receiver) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
* call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
* in the same transaction.
* - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
* deposit would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewDeposit(uint256 assets) external view returns (uint256 shares);
/**
* @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* deposit execution, and are accounted for during deposit.
* - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
* - MUST return a limited value if receiver is subject to some mint limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
* - MUST NOT revert.
*/
function maxMint(address receiver) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
* in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
* same transaction.
* - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
* would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by minting.
*/
function previewMint(uint256 shares) external view returns (uint256 assets);
/**
* @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
* execution, and are accounted for during mint.
* - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function mint(uint256 shares, address receiver) external returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
* Vault, through a withdraw call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxWithdraw(address owner) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
* call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
* called
* in the same transaction.
* - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
* the withdrawal would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewWithdraw(uint256 assets) external view returns (uint256 shares);
/**
* @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* withdraw execution, and are accounted for during withdraw.
* - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function withdraw(
uint256 assets,
address receiver,
address owner
) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
* through a redeem call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxRedeem(address owner) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
* in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
* same transaction.
* - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
* redemption would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by redeeming.
*/
function previewRedeem(uint256 shares) external view returns (uint256 assets);
/**
* @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* redeem execution, and are accounted for during redeem.
* - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function redeem(
uint256 shares,
address receiver,
address owner
) external returns (uint256 assets);
}// 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"
]
}
},
"remappings": []
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_v3Vault","type":"address"},{"internalType":"string","name":"name_","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":"balanceOfVault","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":[{"internalType":"address","name":"_vault","type":"address"}],"name":"clone","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","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"}],"name":"clone","outputs":[{"internalType":"address","name":"newStrategy","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_v3Vault","type":"address"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"address","name":"_strategist","type":"address"},{"internalType":"address","name":"_rewards","type":"address"},{"internalType":"address","name":"_keeper","type":"address"}],"name":"cloneV3Router","outputs":[{"internalType":"address","name":"_newV3Router","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":"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":[{"internalType":"uint256","name":"callCostInWei","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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_v3Vault","type":"address"},{"internalType":"string","name":"name_","type":"string"}],"name":"initializeThis","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":[],"name":"setEmergencyExit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_forceHarvestTriggerOnce","type":"bool"}],"name":"setForceHarvestTriggerOnce","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":"_newMaxLoss","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":"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":"v3Vault","outputs":[{"internalType":"contract IVault","name":"","type":"address"}],"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"}]Contract Creation Code
6080604052600b805461ff0019166101001790553480156200002057600080fd5b506040516200408338038062004083833981016040819052620000439162000891565b828062000053813380806200006b565b506200006290508282620002d6565b50505062000cbe565b6006546001600160a01b031615620000ca5760405162461bcd60e51b815260206004820152601c60248201527f537472617465677920616c726561647920696e697469616c697a65640000000060448201526064015b60405180910390fd5b600280546001600160a01b0319166001600160a01b03861690811790915560408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa15801562000124573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200014a919062000971565b600680546001600160a01b0319166001600160a01b0392909216918217905562000184908560001962000467602090811b62001c0c17901c565b600380546001600160a01b038086166001600160a01b031992831617909255600480548584169083161781556005805485851693169290921790915562278d006008556002546040805163313ce56760e01b81529051919093169263313ce56792818101926020929091908290030181865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f919062000996565b6200023c90600a62000ac5565b6200024b90620f424062000ad3565b600a556002546004805460405163095ea7b360e01b81526001600160a01b039182169281019290925260001960248301529091169063095ea7b3906044016020604051808303816000875af1158015620002a9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002cf919062000aed565b5050505050565b600b546201000090046001600160a01b031615620003265760405162461bcd60e51b815260206004820152600c60248201526b085a5b9a5d1a585b1a5e995960a21b6044820152606401620000c1565b600654604080516338d52e0f60e01b815290516001600160a01b03928316928516916338d52e0f9160048083019260209291908290030181865afa15801562000373573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000399919062000971565b6001600160a01b031614620003de5760405162461bcd60e51b815260206004820152600a6024820152691ddc9bdb99c81dd85b9d60b21b6044820152606401620000c1565b60065462000405906001600160a01b03168360001962000467602090811b62001c0c17901c565b600b805462010000600160b01b031916620100006001600160a01b038516021790556001600c55600d6200043a828262000b9f565b505060018054610100600160a81b03191674ddcea799ff1699e98edf118e0629a974df7df0120017905550565b801580620004e55750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015620004bd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004e3919062000996565b155b620005595760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401620000c1565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152620005b1918591620005b616565b505050565b600062000612826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166200069460201b62001d59179092919060201c565b805190915015620005b1578080602001905181019062000633919062000aed565b620005b15760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401620000c1565b6060620006a58484600085620006ad565b949350505050565b606082471015620007105760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401620000c1565b600080866001600160a01b031685876040516200072e919062000c6b565b60006040518083038185875af1925050503d80600081146200076d576040519150601f19603f3d011682016040523d82523d6000602084013e62000772565b606091505b509092509050620007868783838762000791565b979650505050505050565b6060831562000805578251600003620007fd576001600160a01b0385163b620007fd5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620000c1565b5081620006a5565b620006a583838151156200081c5781518083602001fd5b8060405162461bcd60e51b8152600401620000c1919062000c89565b80516001600160a01b03811681146200085057600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620008885781810151838201526020016200086e565b50506000910152565b600080600060608486031215620008a757600080fd5b620008b28462000838565b9250620008c26020850162000838565b60408501519092506001600160401b0380821115620008e057600080fd5b818601915086601f830112620008f557600080fd5b8151818111156200090a576200090a62000855565b604051601f8201601f19908116603f0116810190838211818310171562000935576200093562000855565b816040528281528960208487010111156200094f57600080fd5b620009628360208301602088016200086b565b80955050505050509250925092565b6000602082840312156200098457600080fd5b6200098f8262000838565b9392505050565b600060208284031215620009a957600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000a07578160001904821115620009eb57620009eb620009b0565b80851615620009f957918102915b93841c9390800290620009cb565b509250929050565b60008262000a205750600162000abf565b8162000a2f5750600062000abf565b816001811462000a48576002811462000a535762000a73565b600191505062000abf565b60ff84111562000a675762000a67620009b0565b50506001821b62000abf565b5060208310610133831016604e8410600b841016171562000a98575081810a62000abf565b62000aa48383620009c6565b806000190482111562000abb5762000abb620009b0565b0290505b92915050565b60006200098f838362000a0f565b808202811582820484141762000abf5762000abf620009b0565b60006020828403121562000b0057600080fd5b815180151581146200098f57600080fd5b600181811c9082168062000b2657607f821691505b60208210810362000b4757634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620005b157600081815260208120601f850160051c8101602086101562000b765750805b601f850160051c820191505b8181101562000b975782815560010162000b82565b505050505050565b81516001600160401b0381111562000bbb5762000bbb62000855565b62000bd38162000bcc845462000b11565b8462000b4d565b602080601f83116001811462000c0b576000841562000bf25750858301515b600019600386901b1c1916600185901b17855562000b97565b600085815260208120601f198616915b8281101562000c3c5788860151825594840194600190910190840162000c1b565b508582101562000c5b5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000825162000c7f8184602087016200086b565b9190910192915050565b602081526000825180602084015262000caa8160408501602087016200086b565b601f01601f19169190910160400192915050565b6133b58062000cce6000396000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c8063780022a01161019d578063b252720b116100e9578063ed882c2b116100a2578063f8c8765e1161007c578063f8c8765e14610634578063fbfa77cf14610647578063fcf2d0ad1461065a578063fe2508a61461066257600080fd5b8063ed882c2b14610606578063efbb5cb014610619578063f017c92f1461062157600080fd5b8063b252720b1461059a578063c1a3d44c146105b2578063c7b9d530146105ba578063ce5494bb146105cd578063d0511842146105e0578063ec38a862146105f357600080fd5b80639994673d11610156578063a763cf5b11610130578063a763cf5b1461055e578063aa5480cf1461056b578063ac00ff2614610574578063aced16611461058757600080fd5b80639994673d146105305780639ec5a894146105385780639f450b5a1461054b57600080fd5b8063780022a0146104dc5780638124b78e146104ed578063826cddf6146105005780638e6350e21461051857806395326e2d1461051f57806395e80c501461052757600080fd5b8063258294101161025c5780635641ec03116102155780636718835f116101ef5780636718835f146104975780636f392ce7146104a4578063748747e6146104b6578063750521f5146104c957600080fd5b80635641ec031461046d5780635783fe391461047a578063650d18801461048357600080fd5b806325829410146103ff57806328b7ccf7146104205780632e1a7d4d1461043757806339a172a81461044a578063440368a31461045d5780634641257d1461046557600080fd5b806311bc8245116102ae57806311bc8245146103885780631f1fcd511461039b5780631fe4a686146103ae57806321397853146103c157806322f3e2d4146103d457806324be6628146103ec57600080fd5b806301681a62146102f657806303ee438c1461030b57806306fdde031461032957806307661c9714610331578063080f96b3146103445780630ada4dab14610375575b600080fd5b610309610304366004612b84565b610675565b005b610313610820565b6040516103209190612bf1565b60405180910390f35b6103136108ae565b61030961033f366004612cd1565b610940565b600b5461035d906201000090046001600160a01b031681565b6040516001600160a01b039091168152602001610320565b610309610383366004612d2f565b610aba565b610309610396366004612b84565b610b0a565b60065461035d906001600160a01b031681565b60035461035d906001600160a01b031681565b61035d6103cf366004612d4c565b610b76565b6103dc610bf1565b6040519015158152602001610320565b6103096103fa366004612de7565b610c7f565b60408051808201909152600581526418171a171b60d91b6020820152610313565b61042960085481565b604051908152602001610320565b610429610445366004612de7565b610cc9565b610309610458366004612de7565b610d3d565b610309610d7a565b610309610df8565b6009546103dc9060ff1681565b610429600c5481565b6103dc610491366004612de7565b50600090565b6001546103dc9060ff1681565b600b546103dc90610100900460ff1681565b6103096104c4366004612b84565b6111a6565b6103096104d7366004612e00565b61120f565b6104296104ea366004612de7565b90565b61035d6104fb366004612b84565b611262565b60095461035d9061010090046001600160a01b031681565b6000610429565b6103dc611276565b61042960075481565b61042961130b565b60045461035d906001600160a01b031681565b610309610559366004612b84565b6113e5565b600b546103dc9060ff1681565b610429600a5481565b610309610582366004612d2f565b611443565b60055461035d906001600160a01b031681565b60015461035d9061010090046001600160a01b031681565b610429611493565b6103096105c8366004612b84565b6114c4565b6103096105db366004612b84565b61152d565b61035d6105ee366004612e72565b611658565b610309610601366004612b84565b611797565b6103dc610614366004612de7565b6118f5565b610429611a45565b61030961062f366004612de7565b611a61565b610309610642366004612e72565b611a9e565b60025461035d906001600160a01b031681565b610309611ab0565b610309610670366004612de7565b611bcf565b61067d611d70565b6006546001600160a01b03908116908216036106c85760405162461bcd60e51b8152602060048201526005602482015264085dd85b9d60da1b60448201526064015b60405180910390fd5b6002546001600160a01b03908116908216036107105760405162461bcd60e51b81526020600482015260076024820152662173686172657360c81b60448201526064016106bf565b606060005b81518110156107975781818151811061073057610730612ece565b60200260200101516001600160a01b0316836001600160a01b0316036107855760405162461bcd60e51b815260206004820152600a602482015269085c1c9bdd1958dd195960b21b60448201526064016106bf565b8061078f81612efa565b915050610715565b5061081c6107a3611d95565b6040516370a0823160e01b81523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa1580156107e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080b9190612f13565b6001600160a01b0385169190611e03565b5050565b6000805461082d90612f2c565b80601f016020809104026020016040519081016040528092919081815260200182805461085990612f2c565b80156108a65780601f1061087b576101008083540402835291602001916108a6565b820191906000526020600020905b81548152906001019060200180831161088957829003601f168201915b505050505081565b6060600d80546108bd90612f2c565b80601f01602080910402602001604051908101604052809291908181526020018280546108e990612f2c565b80156109365780601f1061090b57610100808354040283529160200191610936565b820191906000526020600020905b81548152906001019060200180831161091957829003601f168201915b5050505050905090565b600b546201000090046001600160a01b03161561098e5760405162461bcd60e51b815260206004820152600c60248201526b085a5b9a5d1a585b1a5e995960a21b60448201526064016106bf565b600654604080516338d52e0f60e01b815290516001600160a01b03928316928516916338d52e0f9160048083019260209291908290030181865afa1580156109da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109fe9190612f60565b6001600160a01b031614610a415760405162461bcd60e51b815260206004820152600a6024820152691ddc9bdb99c81dd85b9d60b21b60448201526064016106bf565b600654610a5a906001600160a01b031683600019611c0c565b600b805462010000600160b01b031916620100006001600160a01b038516021790556001600c55600d610a8d8282612fcb565b505060018054610100600160a81b03191674ddcea799ff1699e98edf118e0629a974df7df0120017905550565b610ac2611e33565b600b805460ff19168215159081179091556040519081527f6ad28df1b554fa6cacd46ae82fa811748d53798feeb437ddf234bf3083953319906020015b60405180910390a150565b610b12611e33565b6040516001600160a01b03821681527fc8db9c35f716b87af1fbb83f03c78646061931269301fd7ba6dcf189b4cdc2fc9060200160405180910390a1600180546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6000610b8487858585611658565b6040516307661c9760e01b81529091506001600160a01b038216906307661c9790610bb5908990899060040161308b565b600060405180830381600087803b158015610bcf57600080fd5b505af1158015610be3573d6000803e3d6000fd5b505050509695505050505050565b6002546040516339ebf82360e01b815230600482015260009182916001600160a01b03909116906339ebf8239060240161012060405180830381865afa158015610c3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6391906130af565b604001511180610c7a57506000610c78611a45565b115b905090565b610c87611ed5565b612710811115610cc45760405162461bcd60e51b81526020600482015260086024820152670e8dede40d0d2ced60c31b60448201526064016106bf565b600c55565b6002546000906001600160a01b03163314610d0f5760405162461bcd60e51b8152602060048201526006602482015265085d985d5b1d60d21b60448201526064016106bf565b6000610d1a83611ef1565b600654909350909150610d37906001600160a01b03163383611e03565b50919050565b610d45611ed5565b60078190556040518181527fbb2c369a0355a34b02ab5fce0643150c87e1c8dfe7c918d465591879f57948b190602001610aff565b610d82612126565b6002546040805163bf3759b560e01b81529051610df6926001600160a01b03169163bf3759b59160048083019260209291908290030181865afa158015610dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df19190612f13565b61227b565b565b610e00612126565b6000806000600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c9190612f13565b60095490915060009060ff1615610ed9576000610e9761237b565b905082811015610eb257610eab818461312a565b9350610ec7565b82811115610ec757610ec4838261312a565b94505b610ed1848461312a565b915050610eea565b610ee282612476565b919550935090505b600b805460ff19169055604051600081527f6ad28df1b554fa6cacd46ae82fa811748d53798feeb437ddf234bf30839533199060200160405180910390a16002546040516339ebf82360e01b81523060048201526000916001600160a01b0316906339ebf8239060240161012060405180830381865afa158015610f72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9691906130af565b60c001516002546040516328766ebf60e21b81526004810188905260248101879052604481018590529192506001600160a01b03169063a1d9bafc906064016020604051808303816000875af1158015610ff4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110189190612f13565b92506110238361227b565b60015460ff168015611044575060015461010090046001600160a01b031615155b156111165760015460405163c70fa00b60e01b815260048101879052602481018690526044810184905260648101859052608481018390526101009091046001600160a01b03169063c70fa00b9060a401602060405180830381865afa1580156110b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d6919061313d565b6111115760405162461bcd60e51b815260206004820152600c60248201526b216865616c7468636865636b60a01b60448201526064016106bf565b611157565b604051600181527ff769f6bf659bbbdabf212d830720ce893eedc57f25ebb8e44edf5b300618a35b9060200160405180910390a16001805460ff1916811790555b6040805186815260208101869052908101839052606081018490527f4c0f499ffe6befa0ca7c826b0916cf87bea98de658013e76938489368d60d5099060800160405180910390a15050505050565b6111ae611ed5565b6001600160a01b0381166111c157600080fd5b600580546001600160a01b0319166001600160a01b0383169081179091556040519081527f2f202ddb4a2e345f6323ed90f8fc8559d770a7abbbeee84dde8aca3351fe715490602001610aff565b611217611ed5565b600061122482848361315a565b507f300e67d5a415b6d015a471d9c7b95dd58f3e8290af965e84e0f845de2996dda6828260405161125692919061321a565b60405180910390a15050565b600061127082333333611658565b92915050565b60095460009061010090046001600160a01b03166112945750600190565b600960019054906101000a90046001600160a01b03166001600160a01b03166334a9e75c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112e7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7a919061313d565b600b546040516370a0823160e01b81523060048201526000916201000090046001600160a01b0316906307a2d13a9082906370a0823190602401602060405180830381865afa158015611362573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113869190612f13565b6040518263ffffffff1660e01b81526004016113a491815260200190565b602060405180830381865afa1580156113c1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7a9190612f13565b6113ed611e33565b60098054610100600160a81b0319166101006001600160a01b038416908102919091179091556040519081527f711be97287cb9ec921887b9be36e148e1a27c6b158547b22b9704ffc54447a0f90602001610aff565b61144b611e33565b60405181151581527ff769f6bf659bbbdabf212d830720ce893eedc57f25ebb8e44edf5b300618a35b9060200160405180910390a16001805460ff1916911515919091179055565b6006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a08231906024016113a4565b6114cc611ed5565b6001600160a01b0381166114df57600080fd5b600380546001600160a01b0319166001600160a01b0383169081179091556040519081527f352ececae6d7d1e6d26bcf2c549dfd55be1637e9b22dc0cf3b71ddb36097a6b490602001610aff565b6002546001600160a01b0316331461154457600080fd5b6002546040805163fbfa77cf60e01b815290516001600160a01b039283169284169163fbfa77cf9160048083019260209291908290030181865afa158015611590573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115b49190612f60565b6001600160a01b0316146115c757600080fd5b6115d081612574565b6006546040516370a0823160e01b81523060048201526116559183916001600160a01b03909116906370a0823190602401602060405180830381865afa15801561161e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116429190612f13565b6006546001600160a01b03169190611e03565b50565b600b54600090610100900460ff1661169b5760405162461bcd60e51b815260206004820152600660248201526521636c6f6e6560d01b60448201526064016106bf565b604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81523060601b601482018190526e5af43d82803e903d91602b57fd5bf360881b6028830152906037816000f0604051637c643b2f60e11b81526001600160a01b038981166004830152888116602483015287811660448301528681166064830152919450908416915063f8c8765e90608401600060405180830381600087803b15801561174257600080fd5b505af1158015611756573d6000803e3d6000fd5b50506040516001600160a01b03851692507f783540fb4221a3238720dc7038937d0d79982bcf895274aa6ad179f82cf0d53c9150600090a250949350505050565b61179f61266d565b6001600160a01b0381166117b257600080fd5b6002546004805460405163095ea7b360e01b81526001600160a01b0391821692810192909252600060248301529091169063095ea7b3906044016020604051808303816000875af115801561180b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061182f919061313d565b50600480546001600160a01b0319166001600160a01b03838116918217835560025460405163095ea7b360e01b8152938401929092526000196024840152169063095ea7b3906044016020604051808303816000875af1158015611897573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118bb919061313d565b506040516001600160a01b03821681527fafbb66abf8f3b719799940473a4052a3717cdd8e40fb6c8a3faadab316b1a06990602001610aff565b60006118ff610bf1565b61190b57506000919050565b611913611276565b61191f57506000919050565b600b5460ff161561193257506001919050565b6002546040516339ebf82360e01b81523060048201526000916001600160a01b0316906339ebf8239060240161012060405180830381865afa15801561197c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a091906130af565b90506008548160a00151426119b5919061312a565b106119c35750600192915050565b600a54600260009054906101000a90046001600160a01b03166001600160a01b031663112c1f9b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3d9190612f13565b119392505050565b6000611a4f61130b565b611a57611493565b610c7a9190613249565b611a69611ed5565b60088190556040518181527f5430e11864ad7aa9775b07d12657fe52df9aa2ba734355bd8ef8747be2c800c590602001610aff565b611aaa848484846126a6565b50505050565b611ab86128f0565b6009805460ff191660011790556002546040516339ebf82360e01b81523060048201526001600160a01b03909116906339ebf8239060240161012060405180830381865afa158015611b0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3291906130af565b6040015115611ba457600260009054906101000a90046001600160a01b03166001600160a01b031663a0e4af9a6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611b8b57600080fd5b505af1158015611b9f573d6000803e3d6000fd5b505050505b6040517f97e963041e952738788b9d4871d854d282065b8f90a464928d6528f2e9a4fd0b90600090a1565b611bd7611e33565b600a8190556040518181527fe5ef7832c564a10cbe7b4f1e01ac33a406cb63fcf430a97a9af8616d150af5f390602001610aff565b801580611c865750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611c60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c849190612f13565b155b611cf15760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b60648201526084016106bf565b6040516001600160a01b038316602482015260448101829052611d5490849063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261290c565b505050565b6060611d6884846000856129de565b949350505050565b611d78611d95565b6001600160a01b0316336001600160a01b031614610df657600080fd5b60025460408051635aa6e67560e01b815290516000926001600160a01b031691635aa6e6759160048083019260209291908290030181865afa158015611ddf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7a9190612f60565b6040516001600160a01b038316602482015260448101829052611d5490849063a9059cbb60e01b90606401611d1d565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eaa9190612f60565b6001600160a01b0316336001600160a01b03161480611ecc5750611d78611d95565b610df657600080fd5b6003546001600160a01b0316331480611ecc5750611d78611d95565b6000806000611efe611493565b9050808411156120fe57600b54604051636c82bbbf60e11b8152306004820152611ff5918691620100009091046001600160a01b0316906307a2d13a90829063d905777e90602401602060405180830381865afa158015611f63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f879190612f13565b6040518263ffffffff1660e01b8152600401611fa591815260200190565b602060405180830381865afa158015611fc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fe69190612f13565b611ff09084613249565b612ab9565b9350808411156120fe57600b546201000090046001600160a01b0316639f40a7b38163c6e6f592612026858961312a565b6040518263ffffffff1660e01b815260040161204491815260200190565b602060405180830381865afa158015612061573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120859190612f13565b600c546040516001600160e01b031960e085901b16815260048101929092523060248301819052604483015260648201526084016020604051808303816000875af11580156120d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120fc9190612f13565b505b612106611493565b90508084111561211c5791505080820381612120565b8392505b50915091565b6005546001600160a01b031633148061214957506003546001600160a01b031633145b8061216c5750612157611d95565b6001600160a01b0316336001600160a01b0316145b806121fe5750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e99190612f60565b6001600160a01b0316336001600160a01b0316145b80611ecc5750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b8152600401602060405180830381865afa158015612257573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d789190612f60565b60006122f9612288611493565b600b5460405163402d267d60e01b8152306004820152620100009091046001600160a01b03169063402d267d90602401602060405180830381865afa1580156122d5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ff09190612f13565b9050801561081c57600b54604051636e553f6560e01b815260048101839052306024820152620100009091046001600160a01b031690636e553f65906044016020604051808303816000875af1158015612357573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d549190612f13565b600b546040516370a0823160e01b81523060048201526000916201000090046001600160a01b031690639f40a7b39082906370a0823190602401602060405180830381865afa1580156123d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123f69190612f13565b600c546040516001600160e01b031960e085901b16815260048101929092523060248301819052604483015260648201526084016020604051808303816000875af1158015612449573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061246d9190612f13565b50610c7a611493565b600080600080612484611a45565b6002546040516339ebf82360e01b81523060048201529192506000916001600160a01b03909116906339ebf8239060240161012060405180830381865afa1580156124d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124f791906130af565b60c0015190508181101561250f578082039450612515565b81810393505b60008061252a612525888a613249565b611ef1565b909250905085156125495761253f8187613249565b9550819450612569565b868111156125605760009650945092508284612569565b80870396508794505b505050509193909250565b600b546040516370a0823160e01b81523060048201526000916201000090046001600160a01b0316906370a0823190602401602060405180830381865afa1580156125c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e79190612f13565b9050801561081c57600b5460405163a9059cbb60e01b81526001600160a01b03848116600483015260248201849052620100009092049091169063a9059cbb906044016020604051808303816000875af1158015612649573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d54919061313d565b612675611d95565b6001600160a01b0316336001600160a01b03161480611ecc57506003546001600160a01b03163314610df657600080fd5b6006546001600160a01b0316156126ff5760405162461bcd60e51b815260206004820152601c60248201527f537472617465677920616c726561647920696e697469616c697a65640000000060448201526064016106bf565b600280546001600160a01b0319166001600160a01b03861690811790915560408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa158015612758573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277c9190612f60565b600680546001600160a01b0319166001600160a01b039290921691821790556127a89085600019611c0c565b600380546001600160a01b038086166001600160a01b031992831617909255600480548584169083161781556005805485851693169290921790915562278d006008556002546040805163313ce56760e01b81529051919093169263313ce56792818101926020929091908290030181865afa15801561282c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128509190612f13565b61285b90600a613340565b61286890620f424061334c565b600a556002546004805460405163095ea7b360e01b81526001600160a01b039182169281019290925260001960248301529091169063095ea7b3906044016020604051808303816000875af11580156128c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128e9919061313d565b5050505050565b6003546001600160a01b031633148061216c5750612157611d95565b6000612961826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611d599092919063ffffffff16565b805190915015611d54578080602001905181019061297f919061313d565b611d545760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016106bf565b606082471015612a3f5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016106bf565b600080866001600160a01b03168587604051612a5b9190613363565b60006040518083038185875af1925050503d8060008114612a98576040519150601f19603f3d011682016040523d82523d6000602084013e612a9d565b606091505b5091509150612aae87838387612ad1565b979650505050505050565b6000818310612ac85781612aca565b825b9392505050565b60608315612b40578251600003612b39576001600160a01b0385163b612b395760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106bf565b5081611d68565b611d688383815115612b555781518083602001fd5b8060405162461bcd60e51b81526004016106bf9190612bf1565b6001600160a01b038116811461165557600080fd5b600060208284031215612b9657600080fd5b8135612aca81612b6f565b60005b83811015612bbc578181015183820152602001612ba4565b50506000910152565b60008151808452612bdd816020860160208601612ba1565b601f01601f19169290920160200192915050565b602081526000612aca6020830184612bc5565b634e487b7160e01b600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715612c3e57612c3e612c04565b60405290565b600082601f830112612c5557600080fd5b813567ffffffffffffffff80821115612c7057612c70612c04565b604051601f8301601f19908116603f01168101908282118183101715612c9857612c98612c04565b81604052838152866020858801011115612cb157600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215612ce457600080fd5b8235612cef81612b6f565b9150602083013567ffffffffffffffff811115612d0b57600080fd5b612d1785828601612c44565b9150509250929050565b801515811461165557600080fd5b600060208284031215612d4157600080fd5b8135612aca81612d21565b60008060008060008060c08789031215612d6557600080fd5b8635612d7081612b6f565b95506020870135612d8081612b6f565b9450604087013567ffffffffffffffff811115612d9c57600080fd5b612da889828a01612c44565b9450506060870135612db981612b6f565b92506080870135612dc981612b6f565b915060a0870135612dd981612b6f565b809150509295509295509295565b600060208284031215612df957600080fd5b5035919050565b60008060208385031215612e1357600080fd5b823567ffffffffffffffff80821115612e2b57600080fd5b818501915085601f830112612e3f57600080fd5b813581811115612e4e57600080fd5b866020828501011115612e6057600080fd5b60209290920196919550909350505050565b60008060008060808587031215612e8857600080fd5b8435612e9381612b6f565b93506020850135612ea381612b6f565b92506040850135612eb381612b6f565b91506060850135612ec381612b6f565b939692955090935050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201612f0c57612f0c612ee4565b5060010190565b600060208284031215612f2557600080fd5b5051919050565b600181811c90821680612f4057607f821691505b602082108103610d3757634e487b7160e01b600052602260045260246000fd5b600060208284031215612f7257600080fd5b8151612aca81612b6f565b601f821115611d5457600081815260208120601f850160051c81016020861015612fa45750805b601f850160051c820191505b81811015612fc357828155600101612fb0565b505050505050565b815167ffffffffffffffff811115612fe557612fe5612c04565b612ff981612ff38454612f2c565b84612f7d565b602080601f83116001811461302e57600084156130165750858301515b600019600386901b1c1916600185901b178555612fc3565b600085815260208120601f198616915b8281101561305d5788860151825594840194600190910190840161303e565b508582101561307b5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b0383168152604060208201819052600090611d6890830184612bc5565b600061012082840312156130c257600080fd5b6130ca612c1a565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152508091505092915050565b8181038181111561127057611270612ee4565b60006020828403121561314f57600080fd5b8151612aca81612d21565b67ffffffffffffffff83111561317257613172612c04565b613186836131808354612f2c565b83612f7d565b6000601f8411600181146131ba57600085156131a25750838201355b600019600387901b1c1916600186901b1783556128e9565b600083815260209020601f19861690835b828110156131eb57868501358255602094850194600190920191016131cb565b50868210156132085760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b8082018082111561127057611270612ee4565b600181815b8085111561329757816000190482111561327d5761327d612ee4565b8085161561328a57918102915b93841c9390800290613261565b509250929050565b6000826132ae57506001611270565b816132bb57506000611270565b81600181146132d157600281146132db576132f7565b6001915050611270565b60ff8411156132ec576132ec612ee4565b50506001821b611270565b5060208310610133831016604e8410600b841016171561331a575081810a611270565b613324838361325c565b806000190482111561333857613338612ee4565b029392505050565b6000612aca838361329f565b808202811582820484141761127057611270612ee4565b60008251613375818460208701612ba1565b919091019291505056fea2646970667358221220fccd0f92bf4e816949da27d789e7b4c73aa71d7c44a4fa27090fb75e5fd0111364736f6c634300081200330000000000000000000000003b27f92c0e212c671ea351827edf93db27cc0c65000000000000000000000000310b7ea7475a0b449cfd73be81522f1b88efafaa000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000125633207976555344542d3120526f757465720000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102f15760003560e01c8063780022a01161019d578063b252720b116100e9578063ed882c2b116100a2578063f8c8765e1161007c578063f8c8765e14610634578063fbfa77cf14610647578063fcf2d0ad1461065a578063fe2508a61461066257600080fd5b8063ed882c2b14610606578063efbb5cb014610619578063f017c92f1461062157600080fd5b8063b252720b1461059a578063c1a3d44c146105b2578063c7b9d530146105ba578063ce5494bb146105cd578063d0511842146105e0578063ec38a862146105f357600080fd5b80639994673d11610156578063a763cf5b11610130578063a763cf5b1461055e578063aa5480cf1461056b578063ac00ff2614610574578063aced16611461058757600080fd5b80639994673d146105305780639ec5a894146105385780639f450b5a1461054b57600080fd5b8063780022a0146104dc5780638124b78e146104ed578063826cddf6146105005780638e6350e21461051857806395326e2d1461051f57806395e80c501461052757600080fd5b8063258294101161025c5780635641ec03116102155780636718835f116101ef5780636718835f146104975780636f392ce7146104a4578063748747e6146104b6578063750521f5146104c957600080fd5b80635641ec031461046d5780635783fe391461047a578063650d18801461048357600080fd5b806325829410146103ff57806328b7ccf7146104205780632e1a7d4d1461043757806339a172a81461044a578063440368a31461045d5780634641257d1461046557600080fd5b806311bc8245116102ae57806311bc8245146103885780631f1fcd511461039b5780631fe4a686146103ae57806321397853146103c157806322f3e2d4146103d457806324be6628146103ec57600080fd5b806301681a62146102f657806303ee438c1461030b57806306fdde031461032957806307661c9714610331578063080f96b3146103445780630ada4dab14610375575b600080fd5b610309610304366004612b84565b610675565b005b610313610820565b6040516103209190612bf1565b60405180910390f35b6103136108ae565b61030961033f366004612cd1565b610940565b600b5461035d906201000090046001600160a01b031681565b6040516001600160a01b039091168152602001610320565b610309610383366004612d2f565b610aba565b610309610396366004612b84565b610b0a565b60065461035d906001600160a01b031681565b60035461035d906001600160a01b031681565b61035d6103cf366004612d4c565b610b76565b6103dc610bf1565b6040519015158152602001610320565b6103096103fa366004612de7565b610c7f565b60408051808201909152600581526418171a171b60d91b6020820152610313565b61042960085481565b604051908152602001610320565b610429610445366004612de7565b610cc9565b610309610458366004612de7565b610d3d565b610309610d7a565b610309610df8565b6009546103dc9060ff1681565b610429600c5481565b6103dc610491366004612de7565b50600090565b6001546103dc9060ff1681565b600b546103dc90610100900460ff1681565b6103096104c4366004612b84565b6111a6565b6103096104d7366004612e00565b61120f565b6104296104ea366004612de7565b90565b61035d6104fb366004612b84565b611262565b60095461035d9061010090046001600160a01b031681565b6000610429565b6103dc611276565b61042960075481565b61042961130b565b60045461035d906001600160a01b031681565b610309610559366004612b84565b6113e5565b600b546103dc9060ff1681565b610429600a5481565b610309610582366004612d2f565b611443565b60055461035d906001600160a01b031681565b60015461035d9061010090046001600160a01b031681565b610429611493565b6103096105c8366004612b84565b6114c4565b6103096105db366004612b84565b61152d565b61035d6105ee366004612e72565b611658565b610309610601366004612b84565b611797565b6103dc610614366004612de7565b6118f5565b610429611a45565b61030961062f366004612de7565b611a61565b610309610642366004612e72565b611a9e565b60025461035d906001600160a01b031681565b610309611ab0565b610309610670366004612de7565b611bcf565b61067d611d70565b6006546001600160a01b03908116908216036106c85760405162461bcd60e51b8152602060048201526005602482015264085dd85b9d60da1b60448201526064015b60405180910390fd5b6002546001600160a01b03908116908216036107105760405162461bcd60e51b81526020600482015260076024820152662173686172657360c81b60448201526064016106bf565b606060005b81518110156107975781818151811061073057610730612ece565b60200260200101516001600160a01b0316836001600160a01b0316036107855760405162461bcd60e51b815260206004820152600a602482015269085c1c9bdd1958dd195960b21b60448201526064016106bf565b8061078f81612efa565b915050610715565b5061081c6107a3611d95565b6040516370a0823160e01b81523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa1580156107e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080b9190612f13565b6001600160a01b0385169190611e03565b5050565b6000805461082d90612f2c565b80601f016020809104026020016040519081016040528092919081815260200182805461085990612f2c565b80156108a65780601f1061087b576101008083540402835291602001916108a6565b820191906000526020600020905b81548152906001019060200180831161088957829003601f168201915b505050505081565b6060600d80546108bd90612f2c565b80601f01602080910402602001604051908101604052809291908181526020018280546108e990612f2c565b80156109365780601f1061090b57610100808354040283529160200191610936565b820191906000526020600020905b81548152906001019060200180831161091957829003601f168201915b5050505050905090565b600b546201000090046001600160a01b03161561098e5760405162461bcd60e51b815260206004820152600c60248201526b085a5b9a5d1a585b1a5e995960a21b60448201526064016106bf565b600654604080516338d52e0f60e01b815290516001600160a01b03928316928516916338d52e0f9160048083019260209291908290030181865afa1580156109da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109fe9190612f60565b6001600160a01b031614610a415760405162461bcd60e51b815260206004820152600a6024820152691ddc9bdb99c81dd85b9d60b21b60448201526064016106bf565b600654610a5a906001600160a01b031683600019611c0c565b600b805462010000600160b01b031916620100006001600160a01b038516021790556001600c55600d610a8d8282612fcb565b505060018054610100600160a81b03191674ddcea799ff1699e98edf118e0629a974df7df0120017905550565b610ac2611e33565b600b805460ff19168215159081179091556040519081527f6ad28df1b554fa6cacd46ae82fa811748d53798feeb437ddf234bf3083953319906020015b60405180910390a150565b610b12611e33565b6040516001600160a01b03821681527fc8db9c35f716b87af1fbb83f03c78646061931269301fd7ba6dcf189b4cdc2fc9060200160405180910390a1600180546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6000610b8487858585611658565b6040516307661c9760e01b81529091506001600160a01b038216906307661c9790610bb5908990899060040161308b565b600060405180830381600087803b158015610bcf57600080fd5b505af1158015610be3573d6000803e3d6000fd5b505050509695505050505050565b6002546040516339ebf82360e01b815230600482015260009182916001600160a01b03909116906339ebf8239060240161012060405180830381865afa158015610c3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6391906130af565b604001511180610c7a57506000610c78611a45565b115b905090565b610c87611ed5565b612710811115610cc45760405162461bcd60e51b81526020600482015260086024820152670e8dede40d0d2ced60c31b60448201526064016106bf565b600c55565b6002546000906001600160a01b03163314610d0f5760405162461bcd60e51b8152602060048201526006602482015265085d985d5b1d60d21b60448201526064016106bf565b6000610d1a83611ef1565b600654909350909150610d37906001600160a01b03163383611e03565b50919050565b610d45611ed5565b60078190556040518181527fbb2c369a0355a34b02ab5fce0643150c87e1c8dfe7c918d465591879f57948b190602001610aff565b610d82612126565b6002546040805163bf3759b560e01b81529051610df6926001600160a01b03169163bf3759b59160048083019260209291908290030181865afa158015610dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df19190612f13565b61227b565b565b610e00612126565b6000806000600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7c9190612f13565b60095490915060009060ff1615610ed9576000610e9761237b565b905082811015610eb257610eab818461312a565b9350610ec7565b82811115610ec757610ec4838261312a565b94505b610ed1848461312a565b915050610eea565b610ee282612476565b919550935090505b600b805460ff19169055604051600081527f6ad28df1b554fa6cacd46ae82fa811748d53798feeb437ddf234bf30839533199060200160405180910390a16002546040516339ebf82360e01b81523060048201526000916001600160a01b0316906339ebf8239060240161012060405180830381865afa158015610f72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9691906130af565b60c001516002546040516328766ebf60e21b81526004810188905260248101879052604481018590529192506001600160a01b03169063a1d9bafc906064016020604051808303816000875af1158015610ff4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110189190612f13565b92506110238361227b565b60015460ff168015611044575060015461010090046001600160a01b031615155b156111165760015460405163c70fa00b60e01b815260048101879052602481018690526044810184905260648101859052608481018390526101009091046001600160a01b03169063c70fa00b9060a401602060405180830381865afa1580156110b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d6919061313d565b6111115760405162461bcd60e51b815260206004820152600c60248201526b216865616c7468636865636b60a01b60448201526064016106bf565b611157565b604051600181527ff769f6bf659bbbdabf212d830720ce893eedc57f25ebb8e44edf5b300618a35b9060200160405180910390a16001805460ff1916811790555b6040805186815260208101869052908101839052606081018490527f4c0f499ffe6befa0ca7c826b0916cf87bea98de658013e76938489368d60d5099060800160405180910390a15050505050565b6111ae611ed5565b6001600160a01b0381166111c157600080fd5b600580546001600160a01b0319166001600160a01b0383169081179091556040519081527f2f202ddb4a2e345f6323ed90f8fc8559d770a7abbbeee84dde8aca3351fe715490602001610aff565b611217611ed5565b600061122482848361315a565b507f300e67d5a415b6d015a471d9c7b95dd58f3e8290af965e84e0f845de2996dda6828260405161125692919061321a565b60405180910390a15050565b600061127082333333611658565b92915050565b60095460009061010090046001600160a01b03166112945750600190565b600960019054906101000a90046001600160a01b03166001600160a01b03166334a9e75c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112e7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7a919061313d565b600b546040516370a0823160e01b81523060048201526000916201000090046001600160a01b0316906307a2d13a9082906370a0823190602401602060405180830381865afa158015611362573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113869190612f13565b6040518263ffffffff1660e01b81526004016113a491815260200190565b602060405180830381865afa1580156113c1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7a9190612f13565b6113ed611e33565b60098054610100600160a81b0319166101006001600160a01b038416908102919091179091556040519081527f711be97287cb9ec921887b9be36e148e1a27c6b158547b22b9704ffc54447a0f90602001610aff565b61144b611e33565b60405181151581527ff769f6bf659bbbdabf212d830720ce893eedc57f25ebb8e44edf5b300618a35b9060200160405180910390a16001805460ff1916911515919091179055565b6006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a08231906024016113a4565b6114cc611ed5565b6001600160a01b0381166114df57600080fd5b600380546001600160a01b0319166001600160a01b0383169081179091556040519081527f352ececae6d7d1e6d26bcf2c549dfd55be1637e9b22dc0cf3b71ddb36097a6b490602001610aff565b6002546001600160a01b0316331461154457600080fd5b6002546040805163fbfa77cf60e01b815290516001600160a01b039283169284169163fbfa77cf9160048083019260209291908290030181865afa158015611590573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115b49190612f60565b6001600160a01b0316146115c757600080fd5b6115d081612574565b6006546040516370a0823160e01b81523060048201526116559183916001600160a01b03909116906370a0823190602401602060405180830381865afa15801561161e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116429190612f13565b6006546001600160a01b03169190611e03565b50565b600b54600090610100900460ff1661169b5760405162461bcd60e51b815260206004820152600660248201526521636c6f6e6560d01b60448201526064016106bf565b604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81523060601b601482018190526e5af43d82803e903d91602b57fd5bf360881b6028830152906037816000f0604051637c643b2f60e11b81526001600160a01b038981166004830152888116602483015287811660448301528681166064830152919450908416915063f8c8765e90608401600060405180830381600087803b15801561174257600080fd5b505af1158015611756573d6000803e3d6000fd5b50506040516001600160a01b03851692507f783540fb4221a3238720dc7038937d0d79982bcf895274aa6ad179f82cf0d53c9150600090a250949350505050565b61179f61266d565b6001600160a01b0381166117b257600080fd5b6002546004805460405163095ea7b360e01b81526001600160a01b0391821692810192909252600060248301529091169063095ea7b3906044016020604051808303816000875af115801561180b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061182f919061313d565b50600480546001600160a01b0319166001600160a01b03838116918217835560025460405163095ea7b360e01b8152938401929092526000196024840152169063095ea7b3906044016020604051808303816000875af1158015611897573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118bb919061313d565b506040516001600160a01b03821681527fafbb66abf8f3b719799940473a4052a3717cdd8e40fb6c8a3faadab316b1a06990602001610aff565b60006118ff610bf1565b61190b57506000919050565b611913611276565b61191f57506000919050565b600b5460ff161561193257506001919050565b6002546040516339ebf82360e01b81523060048201526000916001600160a01b0316906339ebf8239060240161012060405180830381865afa15801561197c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a091906130af565b90506008548160a00151426119b5919061312a565b106119c35750600192915050565b600a54600260009054906101000a90046001600160a01b03166001600160a01b031663112c1f9b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3d9190612f13565b119392505050565b6000611a4f61130b565b611a57611493565b610c7a9190613249565b611a69611ed5565b60088190556040518181527f5430e11864ad7aa9775b07d12657fe52df9aa2ba734355bd8ef8747be2c800c590602001610aff565b611aaa848484846126a6565b50505050565b611ab86128f0565b6009805460ff191660011790556002546040516339ebf82360e01b81523060048201526001600160a01b03909116906339ebf8239060240161012060405180830381865afa158015611b0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3291906130af565b6040015115611ba457600260009054906101000a90046001600160a01b03166001600160a01b031663a0e4af9a6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611b8b57600080fd5b505af1158015611b9f573d6000803e3d6000fd5b505050505b6040517f97e963041e952738788b9d4871d854d282065b8f90a464928d6528f2e9a4fd0b90600090a1565b611bd7611e33565b600a8190556040518181527fe5ef7832c564a10cbe7b4f1e01ac33a406cb63fcf430a97a9af8616d150af5f390602001610aff565b801580611c865750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611c60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c849190612f13565b155b611cf15760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b60648201526084016106bf565b6040516001600160a01b038316602482015260448101829052611d5490849063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261290c565b505050565b6060611d6884846000856129de565b949350505050565b611d78611d95565b6001600160a01b0316336001600160a01b031614610df657600080fd5b60025460408051635aa6e67560e01b815290516000926001600160a01b031691635aa6e6759160048083019260209291908290030181865afa158015611ddf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7a9190612f60565b6040516001600160a01b038316602482015260448101829052611d5490849063a9059cbb60e01b90606401611d1d565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eaa9190612f60565b6001600160a01b0316336001600160a01b03161480611ecc5750611d78611d95565b610df657600080fd5b6003546001600160a01b0316331480611ecc5750611d78611d95565b6000806000611efe611493565b9050808411156120fe57600b54604051636c82bbbf60e11b8152306004820152611ff5918691620100009091046001600160a01b0316906307a2d13a90829063d905777e90602401602060405180830381865afa158015611f63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f879190612f13565b6040518263ffffffff1660e01b8152600401611fa591815260200190565b602060405180830381865afa158015611fc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fe69190612f13565b611ff09084613249565b612ab9565b9350808411156120fe57600b546201000090046001600160a01b0316639f40a7b38163c6e6f592612026858961312a565b6040518263ffffffff1660e01b815260040161204491815260200190565b602060405180830381865afa158015612061573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120859190612f13565b600c546040516001600160e01b031960e085901b16815260048101929092523060248301819052604483015260648201526084016020604051808303816000875af11580156120d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120fc9190612f13565b505b612106611493565b90508084111561211c5791505080820381612120565b8392505b50915091565b6005546001600160a01b031633148061214957506003546001600160a01b031633145b8061216c5750612157611d95565b6001600160a01b0316336001600160a01b0316145b806121fe5750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e99190612f60565b6001600160a01b0316336001600160a01b0316145b80611ecc5750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b8152600401602060405180830381865afa158015612257573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d789190612f60565b60006122f9612288611493565b600b5460405163402d267d60e01b8152306004820152620100009091046001600160a01b03169063402d267d90602401602060405180830381865afa1580156122d5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ff09190612f13565b9050801561081c57600b54604051636e553f6560e01b815260048101839052306024820152620100009091046001600160a01b031690636e553f65906044016020604051808303816000875af1158015612357573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d549190612f13565b600b546040516370a0823160e01b81523060048201526000916201000090046001600160a01b031690639f40a7b39082906370a0823190602401602060405180830381865afa1580156123d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123f69190612f13565b600c546040516001600160e01b031960e085901b16815260048101929092523060248301819052604483015260648201526084016020604051808303816000875af1158015612449573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061246d9190612f13565b50610c7a611493565b600080600080612484611a45565b6002546040516339ebf82360e01b81523060048201529192506000916001600160a01b03909116906339ebf8239060240161012060405180830381865afa1580156124d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124f791906130af565b60c0015190508181101561250f578082039450612515565b81810393505b60008061252a612525888a613249565b611ef1565b909250905085156125495761253f8187613249565b9550819450612569565b868111156125605760009650945092508284612569565b80870396508794505b505050509193909250565b600b546040516370a0823160e01b81523060048201526000916201000090046001600160a01b0316906370a0823190602401602060405180830381865afa1580156125c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e79190612f13565b9050801561081c57600b5460405163a9059cbb60e01b81526001600160a01b03848116600483015260248201849052620100009092049091169063a9059cbb906044016020604051808303816000875af1158015612649573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d54919061313d565b612675611d95565b6001600160a01b0316336001600160a01b03161480611ecc57506003546001600160a01b03163314610df657600080fd5b6006546001600160a01b0316156126ff5760405162461bcd60e51b815260206004820152601c60248201527f537472617465677920616c726561647920696e697469616c697a65640000000060448201526064016106bf565b600280546001600160a01b0319166001600160a01b03861690811790915560408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa158015612758573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277c9190612f60565b600680546001600160a01b0319166001600160a01b039290921691821790556127a89085600019611c0c565b600380546001600160a01b038086166001600160a01b031992831617909255600480548584169083161781556005805485851693169290921790915562278d006008556002546040805163313ce56760e01b81529051919093169263313ce56792818101926020929091908290030181865afa15801561282c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128509190612f13565b61285b90600a613340565b61286890620f424061334c565b600a556002546004805460405163095ea7b360e01b81526001600160a01b039182169281019290925260001960248301529091169063095ea7b3906044016020604051808303816000875af11580156128c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128e9919061313d565b5050505050565b6003546001600160a01b031633148061216c5750612157611d95565b6000612961826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611d599092919063ffffffff16565b805190915015611d54578080602001905181019061297f919061313d565b611d545760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016106bf565b606082471015612a3f5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016106bf565b600080866001600160a01b03168587604051612a5b9190613363565b60006040518083038185875af1925050503d8060008114612a98576040519150601f19603f3d011682016040523d82523d6000602084013e612a9d565b606091505b5091509150612aae87838387612ad1565b979650505050505050565b6000818310612ac85781612aca565b825b9392505050565b60608315612b40578251600003612b39576001600160a01b0385163b612b395760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106bf565b5081611d68565b611d688383815115612b555781518083602001fd5b8060405162461bcd60e51b81526004016106bf9190612bf1565b6001600160a01b038116811461165557600080fd5b600060208284031215612b9657600080fd5b8135612aca81612b6f565b60005b83811015612bbc578181015183820152602001612ba4565b50506000910152565b60008151808452612bdd816020860160208601612ba1565b601f01601f19169290920160200192915050565b602081526000612aca6020830184612bc5565b634e487b7160e01b600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715612c3e57612c3e612c04565b60405290565b600082601f830112612c5557600080fd5b813567ffffffffffffffff80821115612c7057612c70612c04565b604051601f8301601f19908116603f01168101908282118183101715612c9857612c98612c04565b81604052838152866020858801011115612cb157600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215612ce457600080fd5b8235612cef81612b6f565b9150602083013567ffffffffffffffff811115612d0b57600080fd5b612d1785828601612c44565b9150509250929050565b801515811461165557600080fd5b600060208284031215612d4157600080fd5b8135612aca81612d21565b60008060008060008060c08789031215612d6557600080fd5b8635612d7081612b6f565b95506020870135612d8081612b6f565b9450604087013567ffffffffffffffff811115612d9c57600080fd5b612da889828a01612c44565b9450506060870135612db981612b6f565b92506080870135612dc981612b6f565b915060a0870135612dd981612b6f565b809150509295509295509295565b600060208284031215612df957600080fd5b5035919050565b60008060208385031215612e1357600080fd5b823567ffffffffffffffff80821115612e2b57600080fd5b818501915085601f830112612e3f57600080fd5b813581811115612e4e57600080fd5b866020828501011115612e6057600080fd5b60209290920196919550909350505050565b60008060008060808587031215612e8857600080fd5b8435612e9381612b6f565b93506020850135612ea381612b6f565b92506040850135612eb381612b6f565b91506060850135612ec381612b6f565b939692955090935050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201612f0c57612f0c612ee4565b5060010190565b600060208284031215612f2557600080fd5b5051919050565b600181811c90821680612f4057607f821691505b602082108103610d3757634e487b7160e01b600052602260045260246000fd5b600060208284031215612f7257600080fd5b8151612aca81612b6f565b601f821115611d5457600081815260208120601f850160051c81016020861015612fa45750805b601f850160051c820191505b81811015612fc357828155600101612fb0565b505050505050565b815167ffffffffffffffff811115612fe557612fe5612c04565b612ff981612ff38454612f2c565b84612f7d565b602080601f83116001811461302e57600084156130165750858301515b600019600386901b1c1916600185901b178555612fc3565b600085815260208120601f198616915b8281101561305d5788860151825594840194600190910190840161303e565b508582101561307b5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b0383168152604060208201819052600090611d6890830184612bc5565b600061012082840312156130c257600080fd5b6130ca612c1a565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152508091505092915050565b8181038181111561127057611270612ee4565b60006020828403121561314f57600080fd5b8151612aca81612d21565b67ffffffffffffffff83111561317257613172612c04565b613186836131808354612f2c565b83612f7d565b6000601f8411600181146131ba57600085156131a25750838201355b600019600387901b1c1916600186901b1783556128e9565b600083815260209020601f19861690835b828110156131eb57868501358255602094850194600190920191016131cb565b50868210156132085760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b8082018082111561127057611270612ee4565b600181815b8085111561329757816000190482111561327d5761327d612ee4565b8085161561328a57918102915b93841c9390800290613261565b509250929050565b6000826132ae57506001611270565b816132bb57506000611270565b81600181146132d157600281146132db576132f7565b6001915050611270565b60ff8411156132ec576132ec612ee4565b50506001821b611270565b5060208310610133831016604e8410600b841016171561331a575081810a611270565b613324838361325c565b806000190482111561333857613338612ee4565b029392505050565b6000612aca838361329f565b808202811582820484141761127057611270612ee4565b60008251613375818460208701612ba1565b919091019291505056fea2646970667358221220fccd0f92bf4e816949da27d789e7b4c73aa71d7c44a4fa27090fb75e5fd0111364736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000003b27f92c0e212c671ea351827edf93db27cc0c65000000000000000000000000310b7ea7475a0b449cfd73be81522f1b88efafaa000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000125633207976555344542d3120526f757465720000000000000000000000000000
-----Decoded View---------------
Arg [0] : _vault (address): 0x3B27F92C0e212C671EA351827EDF93DB27cc0c65
Arg [1] : _v3Vault (address): 0x310B7Ea7475A0B449Cfd73bE81522F1B88eFAFaa
Arg [2] : name_ (string): V3 yvUSDT-1 Router
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000003b27f92c0e212c671ea351827edf93db27cc0c65
Arg [1] : 000000000000000000000000310b7ea7475a0b449cfd73be81522f1b88efafaa
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000012
Arg [4] : 5633207976555344542d3120526f757465720000000000000000000000000000
Deployed Bytecode Sourcemap
430:5482:9:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36170:436:11;;;;;;:::i;:::-;;:::i;:::-;;6816:25;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1809:92:9;;;:::i;1247:484::-;;;;;;:::i;:::-;;:::i;540:21::-;;;;;;;;-1:-1:-1;;;;;540:21:9;;;;;;-1:-1:-1;;;;;2907:32:12;;;2889:51;;2877:2;2862:18;540:21:9;2728:218:12;17426:222:11;;;;;;:::i;:::-;;:::i;13207:159::-;;;;;;:::i;:::-;;:::i;8792:18::-;;;;;-1:-1:-1;;;;;8792:18:11;;;8705:25;;;;;-1:-1:-1;;;;;8705:25:11;;;872:369:9;;;;;;:::i;:::-;;:::i;21300:146:11:-;;;:::i;:::-;;;4944:14:12;;4937:22;4919:41;;4907:2;4892:18;21300:146:11;4779:187:12;5496:155:9;;;;;;:::i;:::-;;:::i;7202:89:11:-;7270:14;;;;;;;;;;;;-1:-1:-1;;;7270:14:11;;;;7202:89;;9779:29;;;;;;;;;5302:25:12;;;5290:2;5275:18;9779:29:11;5156:177:12;32588:507:11;;;;;;:::i;:::-;;:::i;15714:151::-;;;;;;:::i;:::-;;:::i;26365:167::-;;;:::i;30625:1729::-;;;:::i;9856:25::-;;;;;;;;;599:22:9;;;;;;25550:497:11;;;;;;:::i;:::-;-1:-1:-1;25623:4:11;;25550:497;6869:25;;;;;;;;;36676:29;;;;;;;;;;;;14501:170;;;;;;:::i;:::-;;:::i;18439:168::-;;;;;;:::i;:::-;;:::i;5778:132:9:-;;;;;;:::i;:::-;5894:9;5778:132;37031:131:11;;;;;;:::i;:::-;;:::i;9938:28::-;;;;;;;;-1:-1:-1;;;;;9938:28:11;;;8580:92;8638:7;8580:92;;29645:193;;;:::i;9632:29::-;;;;;;2156:137:9;;;:::i;8736:22:11:-;;;;;-1:-1:-1;;;;;8736:22:11;;;17971:175;;;;;;:::i;:::-;;:::i;10100:35::-;;;;;;;;;10015:30;;;;;;13372:168;;;;;;:::i;:::-;;:::i;8764:21::-;;;;;-1:-1:-1;;;;;8764:21:11;;;6900:26;;;;;;;;-1:-1:-1;;;;;6900:26:11;;;2042:108:9;;;:::i;13764:198:11:-;;;;;;:::i;:::-;;:::i;33846:276::-;;;;;;:::i;:::-;;:::i;37168:930::-;;;;;;:::i;:::-;;:::i;14950:261::-;;;;;;:::i;:::-;;:::i;28554:848::-;;;;;;:::i;:::-;;:::i;1907:129:9:-;;;:::i;16368:151:11:-;;;;;;:::i;:::-;;:::i;36810:215::-;;;;;;:::i;:::-;;:::i;8678:21::-;;;;;-1:-1:-1;;;;;8678:21:11;;;34539:244;;;:::i;16854:187::-;;;;;;:::i;:::-;;:::i;36170:436::-;10444:17;:15;:17::i;:::-;36261:4:::1;::::0;-1:-1:-1;;;;;36261:4:11;;::::1;36243:23:::0;;::::1;::::0;36235:41:::1;;;::::0;-1:-1:-1;;;36235:41:11;;7038:2:12;36235:41:11::1;::::0;::::1;7020:21:12::0;7077:1;7057:18;;;7050:29;-1:-1:-1;;;7095:18:12;;;7088:35;7140:18;;36235:41:11::1;;;;;;;;;36312:5;::::0;-1:-1:-1;;;;;36312:5:11;;::::1;36294:24:::0;;::::1;::::0;36286:44:::1;;;::::0;-1:-1:-1;;;36286:44:11;;7371:2:12;36286:44:11::1;::::0;::::1;7353:21:12::0;7410:1;7390:18;;;7383:29;-1:-1:-1;;;7428:18:12;;;7421:37;7475:18;;36286:44:11::1;7169:330:12::0;36286:44:11::1;5748:16:9::0;36341:33:11::1;36404:102;36424:16;:23;36420:1;:27;36404:102;;;36472:16;36489:1;36472:19;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1::0;;;;;36462:29:11::1;:6;-1:-1:-1::0;;;;;36462:29:11::1;::::0;36454:52:::1;;;::::0;-1:-1:-1;;;36454:52:11;;7838:2:12;36454:52:11::1;::::0;::::1;7820:21:12::0;7877:2;7857:18;;;7850:30;-1:-1:-1;;;7896:18:12;;;7889:40;7946:18;;36454:52:11::1;7636:334:12::0;36454:52:11::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:11;;36592:4:::1;36559:39;::::0;::::1;2889:51:12::0;-1:-1:-1;;;;;36559:24:11;::::1;::::0;::::1;::::0;2862:18:12;;36559:39:11::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;36517:27:11;::::1;::::0;:82;:27:::1;:82::i;:::-;36225:381;36170:436:::0;:::o;6816:25::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1809:92:9:-;1857:13;1889:5;1882:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1809:92;:::o;1247:484::-;1343:7;;;;;-1:-1:-1;;;;;1343:7:9;1335:30;1327:55;;;;-1:-1:-1;;;1327:55:9;;9023:2:12;1327:55:9;;;9005:21:12;9062:2;9042:18;;;9035:30;-1:-1:-1;;;9081:18:12;;;9074:42;9133:18;;1327:55:9;8821:336:12;1327:55:9;1436:4;;1400:24;;;-1:-1:-1;;;1400:24:9;;;;-1:-1:-1;;;;;1436:4:9;;;;1400:22;;;;;:24;;;;;;;;;;;;;;:22;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;1400:41:9;;1392:64;;;;-1:-1:-1;;;1392:64:9;;9620:2:12;1392:64:9;;;9602:21:12;9659:2;9639:18;;;9632:30;-1:-1:-1;;;9678:18:12;;;9671:40;9728:18;;1392:64:9;9418:334:12;1392:64:9;1467:4;;:45;;-1:-1:-1;;;;;1467:4:9;1484:8;-1:-1:-1;;1467:16:9;:45::i;:::-;1522:7;:26;;-1:-1:-1;;;;;;1522:26:9;;-1:-1:-1;;;;;1522:26:9;;;;;;-1:-1:-1;1594:7:9;:11;1616:5;:13;1624:5;1616;:13;:::i;:::-;-1:-1:-1;;1668:11:9;:56;;-1:-1:-1;;;;;;1668:56:9;;;;;-1:-1:-1;1247:484:9:o;17426:222:11:-;10668:20;:18;:20::i;:::-;17530:23:::1;:50:::0;;-1:-1:-1;;17530:50:11::1;::::0;::::1;;::::0;;::::1;::::0;;;17595:46:::1;::::0;4919:41:12;;;17595:46:11::1;::::0;4907:2:12;4892:18;17595:46:11::1;;;;;;;;17426:222:::0;:::o;13207:159::-;10668:20;:18;:20::i;:::-;13295:28:::1;::::0;-1:-1:-1;;;;;2907:32:12;;2889:51;;13295:28:11::1;::::0;2877:2:12;2862:18;13295:28:11::1;;;;;;;13333:11;:26:::0;;-1:-1:-1;;;;;13333:26:11;;::::1;;;-1:-1:-1::0;;;;;;13333:26:11;;::::1;::::0;;;::::1;::::0;;13207:159::o;872:369:9:-;1078:20;1125:45;1131:6;1139:11;1152:8;1162:7;1125:5;:45::i;:::-;1180:54;;-1:-1:-1;;;1180:54:9;;1110:60;;-1:-1:-1;;;;;;1180:37:9;;;;;:54;;1218:8;;1228:5;;1180:54;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;872:369;;;;;;;;:::o;21300:146:11:-;21364:5;;:31;;-1:-1:-1;;;21364:31:11;;21389:4;21364:31;;;2889:51:12;21341:4:11;;;;-1:-1:-1;;;;;21364:5:11;;;;:16;;2862:18:12;;21364:31:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;:45;:75;;;;21438:1;21413:22;:20;:22::i;:::-;:26;21364:75;21357:82;;21300:146;:::o;5496:155:9:-;10195:17:11;:15;:17::i;:::-;5594:6:9::1;5579:11;:21;;5571:42;;;::::0;-1:-1:-1;;;5571:42:9;;13269:2:12;5571:42:9::1;::::0;::::1;13251:21:12::0;13308:1;13288:18;;;13281:29;-1:-1:-1;;;13326:18:12;;;13319:38;13374:18;;5571:42:9::1;13067:331:12::0;5571:42:9::1;5623:7;:21:::0;5496:155::o;32588:507:11:-;32702:5;;32647:13;;-1:-1:-1;;;;;32702:5:11;32680:10;:28;32672:47;;;;-1:-1:-1;;;32672:47:11;;13605:2:12;32672:47:11;;;13587:21:12;13644:1;13624:18;;;13617:29;-1:-1:-1;;;13662:18:12;;;13655:36;13708:18;;32672:47:11;13403:329:12;32672:47:11;32803:19;32855:32;32873:13;32855:17;:32::i;:::-;32977:4;;32832:55;;-1:-1:-1;32832:55:11;;-1:-1:-1;32977:42:11;;-1:-1:-1;;;;;32977:4:11;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;5302:25:12;;;15829:29:11::1;::::0;5290:2:12;5275:18;15829:29:11::1;5156:177:12::0;26365:167:11;10591:14;:12;:14::i;:::-;26501:5:::1;::::0;:23:::1;::::0;;-1:-1:-1;;;26501:23:11;;;;26486:39:::1;::::0;-1:-1:-1;;;;;26501:5:11::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:11::1;-1:-1:-1::0;;;;;30755:21:11::1;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;30825:13;::::0;30729:49;;-1:-1:-1;30788:19:11::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:11;-1:-1:-1;31309:60:11;-1:-1:-1;30821:559:11::1;31459:23;:31:::0;;-1:-1:-1;;31459:31:11::1;::::0;;31505:27:::1;::::0;-1:-1:-1;4919:41:12;;31505:27:11::1;::::0;4907:2:12;4892:18;31505:27:11::1;;;;;;;31744:5;::::0;:31:::1;::::0;-1:-1:-1;;;31744:31:11;;31769:4:::1;31744:31;::::0;::::1;2889:51:12::0;31724:17:11::1;::::0;-1:-1:-1;;;;;31744:5:11::1;::::0;:16:::1;::::0;2862:18:12;;31744:31:11::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;::::0;31813:5:::1;::::0;:39:::1;::::0;-1:-1:-1;;;31813:39:11;;::::1;::::0;::::1;14072:25:12::0;;;14113:18;;;14106:34;;;14156:18;;;14149:34;;;31744:41:11;;-1:-1:-1;;;;;;31813:5:11::1;::::0;:12:::1;::::0;14045:18:12;;31813:39:11::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:11::1;::::0;::::1;::::0;::::1;-1:-1:-1::0;;;;;32025:11:11::1;:25:::0;::::1;32008:42;32004:275;;;32086:11;::::0;32074:85:::1;::::0;-1:-1:-1;;;32074:85:11;;::::1;::::0;::::1;14453:25:12::0;;;14494:18;;;14487:34;;;14537:18;;;14530:34;;;14580:18;;;14573:34;;;14623:19;;;14616:35;;;32086:11:11::1;::::0;;::::1;-1:-1:-1::0;;;;;32086:11:11::1;::::0;32074:30:::1;::::0;14425:19:12;;32074:85:11::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;32066:110;;;::::0;-1:-1:-1;;;32066:110:11;;15114:2:12;32066:110:11::1;::::0;::::1;15096:21:12::0;15153:2;15133:18;;;15126:30;-1:-1:-1;;;15172:18:12;;;15165:42;15224:18;;32066:110:11::1;14912:336:12::0;32066:110:11::1;32004:275;;;32212:22;::::0;32229:4:::1;4919:41:12::0;;32212:22:11::1;::::0;4907:2:12;4892:18;32212:22:11::1;;;;;;;32264:4;32248:20:::0;;-1:-1:-1;;32248:20:11::1;::::0;::::1;::::0;;32004:275:::1;32294:53;::::0;;15484:25:12;;;15540:2;15525:18;;15518:34;;;15568:18;;;15561:34;;;15626:2;15611:18;;15604:34;;;32294:53:11::1;::::0;15471:3:12;15456:19;32294:53:11::1;;;;;;;30665:1689;;;;;30625:1729::o:0;14501:170::-;10195:17;:15;:17::i;:::-;-1:-1:-1;;;;;14579:21:11;::::1;14571:30;;;::::0;::::1;;14611:6;:16:::0;;-1:-1:-1;;;;;;14611:16:11::1;-1:-1:-1::0;;;;;14611:16:11;::::1;::::0;;::::1;::::0;;;14642:22:::1;::::0;2889:51:12;;;14642:22:11::1;::::0;2877:2:12;2862:18;14642:22:11::1;2728:218:12::0;18439:168:11;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;37031:131::-;37080:7;37106:49;37112:6;37120:10;37132;37144;37106:5;:49::i;:::-;37099:56;37031:131;-1:-1:-1;;37031:131:11:o;29645:193::-;29717:13;;29697:4;;29717:13;;;-1:-1:-1;;;;;29717:13:11;29713:118;;-1:-1:-1;29753:4:11;;29645:193::o;29713:118::-;29788:13;;;;;;;;;-1:-1:-1;;;;;29788:13:11;-1:-1:-1;;;;;29779:50:11;;:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;2156:137:9:-;2229:7;;2253:32;;-1:-1:-1;;;2253:32:9;;2279:4;2253:32;;;2889:51:12;2203:7:9;;2229;;;-1:-1:-1;;;;;2229:7:9;;:23;;:7;;2253:17;;2862:18:12;;2253:32:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2229:57;;;;;;;;;;;;;5302:25:12;;5290:2;5275:18;;5156:177;2229:57:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;17971:175:11:-;10668:20;:18;:20::i;:::-;18058:13:::1;:30:::0;;-1:-1:-1;;;;;;18058:30:11::1;;-1:-1:-1::0;;;;;18058:30:11;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;18103:36:::1;::::0;2889:51:12;;;18103:36:11::1;::::0;2877:2:12;2862:18;18103:36:11::1;2728:218:12::0;13372:168:11;10668:20;:18;:20::i;:::-;13461:32:::1;::::0;4944:14:12;;4937:22;4919:41;;13461:32:11::1;::::0;4907:2:12;4892:18;13461:32:11::1;;;;;;;13503:13;:30:::0;;-1:-1:-1;;13503:30:11::1;::::0;::::1;;::::0;;;::::1;::::0;;13372:168::o;2042:108:9:-;2114:4;;:29;;-1:-1:-1;;;2114:29:9;;2137:4;2114:29;;;2889:51:12;2088:7:9;;-1:-1:-1;;;;;2114:4:9;;:14;;2862:18:12;;2114:29:9;2728:218:12;13764:198:11;10195:17;:15;:17::i;:::-;-1:-1:-1;;;;;13850:25:11;::::1;13842:34;;;::::0;::::1;;13886:10;:24:::0;;-1:-1:-1;;;;;;13886:24:11::1;-1:-1:-1::0;;;;;13886:24:11;::::1;::::0;;::::1;::::0;;;13925:30:::1;::::0;2889:51:12;;;13925:30:11::1;::::0;2877:2:12;2862:18;13925:30:11::1;2728:218:12::0;33846:276:11;33934:5;;-1:-1:-1;;;;;33934:5:11;33912:10;:28;33904:37;;;;;;33997:5;;33959:34;;;-1:-1:-1;;;33959:34:11;;;;-1:-1:-1;;;;;33997:5:11;;;;33959:32;;;;;:34;;;;;;;;;;;;;;:32;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;33959:43:11;;33951:52;;;;;;34013:30;34030:12;34013:16;:30::i;:::-;34085:4;;:29;;-1:-1:-1;;;34085:29:11;;34108:4;34085:29;;;2889:51:12;34053:62:11;;34071:12;;-1:-1:-1;;;;;34085:4:11;;;;:14;;2862:18:12;;34085:29:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;34053:4;;-1:-1:-1;;;;;34053:4:11;;:62;:17;:62::i;:::-;33846:276;:::o;37168:930::-;37348:10;;37309:19;;37348:10;;;;;37340:29;;;;-1:-1:-1;;;37340:29:11;;17730:2:12;37340:29:11;;;17712:21:12;17769:1;17749:18;;;17742:29;-1:-1:-1;;;17787:18:12;;;17780:36;17833:18;;37340:29:11;17528:329:12;37340:29:11;37622:4;37616:11;-1:-1:-1;;;37640:86:11;;37525:4;37509:22;;37762:4;37746:21;;37739:43;;;-1:-1:-1;;;37818:4:11;37802:21;;37795:97;37509:22;37942:4;37616:11;37486:20;37920:27;37967:89;;-1:-1:-1;;;37967:89:11;;-1:-1:-1;;;;;18149:15:12;;;37967:89:11;;;18131:34:12;18201:15;;;18181:18;;;18174:43;18253:15;;;18233:18;;;18226:43;18305:15;;;18285:18;;;18278:43;37905:42:11;;-1:-1:-1;37967:49:11;;;;-1:-1:-1;37967:49:11;;18065:19:12;;37967:89:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;38072:19:11;;-1:-1:-1;;;;;38072:19:11;;;-1:-1:-1;38072:19:11;;-1:-1:-1;38072:19:11;;;37330:768;37168:930;;;;;;:::o;14950:261::-;10519:15;:13;:15::i;:::-;-1:-1:-1;;;;;15028:22:11;::::1;15020:31;;;::::0;::::1;;15061:5;::::0;15075:7:::1;::::0;;15061:25:::1;::::0;-1:-1:-1;;;15061:25:11;;-1:-1:-1;;;;;15075:7:11;;::::1;15061:25:::0;;::::1;18514:51:12::0;;;;15061:5:11::1;18581:18:12::0;;;18574:34;15061:5:11;;::::1;::::0;:13:::1;::::0;18487:18:12;;15061:25:11::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;15096:7:11::1;:18:::0;;-1:-1:-1;;;;;;15096:18:11::1;-1:-1:-1::0;;;;;15096:18:11;;::::1;::::0;;::::1;::::0;;15124:5:::1;::::0;:41:::1;::::0;-1:-1:-1;;;15124:41:11;;;;::::1;18514:51:12::0;;;;-1:-1:-1;;18581:18:12;;;18574:34;15124:5:11::1;::::0;:13:::1;::::0;18487:18:12;;15124:41:11::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;15180:24:11::1;::::0;-1:-1:-1;;;;;2907:32:12;;2889:51;;15180:24:11::1;::::0;2877:2:12;2862:18;15180:24:11::1;2728:218:12::0;28554:848:11;28630:4;28735:10;:8;:10::i;:::-;28730:29;;-1:-1:-1;28754:5:11;;28554:848;-1:-1:-1;28554:848:11:o;28730:29::-;28869:21;:19;:21::i;:::-;28864:40;;-1:-1:-1;28899:5:11;;28554:848;-1:-1:-1;28554:848:11:o;28864:40::-;29010:23;;;;29006:40;;;-1:-1:-1;29042:4:11;;28554:848;-1:-1:-1;28554:848:11:o;29006:40::-;29147:5;;:31;;-1:-1:-1;;;29147:31:11;;29172:4;29147:31;;;2889:51:12;29116:28:11;;-1:-1:-1;;;;;29147:5:11;;:16;;2862:18:12;;29147:31:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;29116:62;;29233:14;;29211:6;:17;;;29193:15;:35;;;;:::i;:::-;29192:55;29188:72;;-1:-1:-1;29256:4:11;;28554:848;-1:-1:-1;;28554:848:11:o;29188:72::-;29379:15;;29353:5;;;;;;;;;-1:-1:-1;;;;;29353:5:11;-1:-1:-1;;;;;29353:21:11;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;28554:848;-1:-1:-1;;;28554:848:11:o;1907:129:9:-;1969:7;2013:16;:14;:16::i;:::-;1995:15;:13;:15::i;:::-;:34;;;;:::i;16368:151:11:-;10195:17;:15;:17::i;:::-;16445:14:::1;:23:::0;;;16483:29:::1;::::0;5302:25:12;;;16483:29:11::1;::::0;5290:2:12;5275:18;16483:29:11::1;5156:177:12::0;36810:215:11;36967:51;36979:6;36987:11;37000:8;37010:7;36967:11;:51::i;:::-;36810:215;;;;:::o;34539:244::-;10281:26;:24;:26::i;:::-;34610:13:::1;:20:::0;;-1:-1:-1;;34610:20:11::1;34626:4;34610:20;::::0;;34644:5:::1;::::0;:31:::1;::::0;-1:-1:-1;;;34644:31:11;;34669:4:::1;34644:31;::::0;::::1;2889:51:12::0;-1:-1:-1;;;;;34644:5:11;;::::1;::::0;:16:::1;::::0;2862:18:12;;34644:31:11::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;::::0;:46;34640:99:::1;;34706:5;;;;;;;;;-1:-1:-1::0;;;;;34706:5:11::1;-1:-1:-1::0;;;;;34706:20:11::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;5302:25:12;;;16994:40:11::1;::::0;5290:2:12;5275:18;16994:40:11::1;5156:177:12::0;1475:603:5;1830:10;;;1829:62;;-1:-1:-1;1846:39:5;;-1:-1:-1;;;1846:39:5;;1870:4;1846:39;;;19240:34:12;-1:-1:-1;;;;;19310:15:12;;;19290:18;;;19283:43;1846:15:5;;;;;19175:18:12;;1846:39:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;1829:62;1808:163;;;;-1:-1:-1;;;1808:163:5;;19539:2:12;1808:163:5;;;19521:21:12;19578:2;19558:18;;;19551:30;19617:34;19597:18;;;19590:62;-1:-1:-1;;;19668:18:12;;;19661:52;19730:19;;1808:163:5;19337:418:12;1808:163:5;2008:62;;-1:-1:-1;;;;;18532:32:12;;2008:62:5;;;18514:51:12;18581:18;;;18574:34;;;1981:90:5;;2001:5;;-1:-1:-1;;;2031:22:5;18487:18:12;;2008:62:5;;;;-1:-1:-1;;2008:62:5;;;;;;;;;;;;;;-1:-1:-1;;;;;2008:62:5;-1:-1:-1;;;;;;2008:62:5;;;;;;;;;;1981:19;:90::i;:::-;1475:603;;;:::o;3873:223:6:-;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:6:o;11127:88:11:-;11195:12;:10;:12::i;:::-;-1:-1:-1;;;;;11181:26:11;:10;-1:-1:-1;;;;;11181:26:11;;11173:35;;;;;18755:96;18826:5;;:18;;;-1:-1:-1;;;18826:18:11;;;;18800:7;;-1:-1:-1;;;;;18826:5:11;;:16;;:18;;;;;;;;;;;;;;:5;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;763:205:5:-;902:58;;-1:-1:-1;;;;;18532:32:12;;902:58:5;;;18514:51:12;18581:18;;;18574:34;;;875:86:5;;895:5;;-1:-1:-1;;;925:23:5;18487:18:12;;902:58:5;18332:282:12;11640:127:11;11711:5;;;;;;;;;-1:-1:-1;;;;;11711:5:11;-1:-1:-1;;;;;11711:16:11;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;11697:32:11;:10;-1:-1:-1;;;;;11697:32:11;;:62;;;;11747:12;:10;:12::i;11697:62::-;11689:71;;;;;10712:116;10780:10;;-1:-1:-1;;;;;10780:10:11;10766;:24;;:54;;;10808:12;:10;:12::i;3893:1098:9:-;3984:25;4011:13;4036:15;4054;:13;:15::i;:::-;4036:33;;4100:7;4084:13;:23;4080:628;;;4288:7;;4312:32;;-1:-1:-1;;;4312:32:9;;4338:4;4312:32;;;2889:51:12;4201:158:9;;4227:13;;4288:7;;;;-1:-1:-1;;;;;4288:7:9;;:23;;:7;;4312:17;;2862:18:12;;4312:32:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4288:57;;;;;;;;;;;;;5302:25:12;;5290:2;5275:18;;5156:177;4288:57:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4258:87;;:7;:87;:::i;:::-;4201:8;:158::i;:::-;4185:174;;4455:7;4439:13;:23;4435:263;;;4482:7;;;;;-1:-1:-1;;;;;4482:7:9;:14;:7;4518:23;4542;4558:7;4542:13;:23;:::i;:::-;4518:48;;;;;;;;;;;;;5302:25:12;;5290:2;5275:18;;5156:177;4518:48:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4658:7;;4482:201;;-1:-1:-1;;;;;;4482:201:9;;;;;;;;;;19991:25:12;;;;4596:4:9;20070:18:12;;;20063:43;;;20122:18;;;20115:43;20174:18;;;20167:34;19963:19;;4482:201:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;4435:263;4728:15;:13;:15::i;:::-;4718:25;;4773:7;4757:13;:23;4753:232;;;4816:7;-1:-1:-1;;4873:23:9;;;4816:7;4753:232;;;4961:13;4941:33;;4753:232;4026:965;3893:1098;;;:::o;11341:293:11:-;11419:6;;-1:-1:-1;;;;;11419:6:11;11405:10;:20;;:64;;-1:-1:-1;11459:10:11;;-1:-1:-1;;;;;11459:10:11;11445;:24;11405:64;:110;;;;11503:12;:10;:12::i;:::-;-1:-1:-1;;;;;11489:26:11;:10;-1:-1:-1;;;;;11489:26:11;;11405:110;:160;;;;11549:5;;;;;;;;;-1:-1:-1;;;;;11549:5:11;-1:-1:-1;;;;;11549:14:11;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;11535:30:11;:10;-1:-1:-1;;;;;11535:30:11;;11405:160;:212;;;;11599:5;;;;;;;;;-1:-1:-1;;;;;11599:5:11;-1:-1:-1;;;;;11599:16:11;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;3614:273:9:-;3675:16;3694:94;3716:15;:13;:15::i;:::-;3745:7;;:33;;-1:-1:-1;;;3745:33:9;;3772:4;3745:33;;;2889:51:12;3745:7:9;;;;-1:-1:-1;;;;;3745:7:9;;:18;;2862::12;;3745:33:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;3694:94::-;3675:113;-1:-1:-1;3802:12:9;;3798:83;;3830:7;;:40;;-1:-1:-1;;;3830:40:9;;;;;20386:25:12;;;3864:4:9;20427:18:12;;;20420:60;3830:7:9;;;;-1:-1:-1;;;;;3830:7:9;;:15;;20359:18:12;;3830:40:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;4997:264::-;5076:7;;5104:32;;-1:-1:-1;;;5104:32:9;;5130:4;5104:32;;;2889:51:12;5057:7:9;;5076;;;-1:-1:-1;;;;;5076:7:9;;:14;;:7;;5104:17;;2862:18:12;;5104:32:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5204:7;;5076:145;;-1:-1:-1;;;;;;5076:145:9;;;;;;;;;;19991:25:12;;;;5158:4:9;20070:18:12;;;20063:43;;;20122:18;;;20115:43;20174:18;;;20167:34;19963:19;;5076:145:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;5239:15;:13;:15::i;2299:1309::-;2413:15;2430:13;2445:20;2481:19;2503:22;:20;:22::i;:::-;2555:5;;:31;;-1:-1:-1;;;2555:31:9;;2580:4;2555:31;;;2889:51:12;2481:44:9;;-1:-1:-1;2535:17:9;;-1:-1:-1;;;;;2555:5:9;;;;:16;;2862:18:12;;2555:31:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;2535:61;;2623:11;2611:9;:23;2607:293;;;2732:9;2718:11;:23;2708:33;;2607:293;;;2864:11;2852:9;:23;2844:31;;2607:293;2911:20;;2950:67;2981:26;3000:7;2981:16;:26;:::i;:::-;2950:17;:67::i;:::-;2910:107;;-1:-1:-1;2910:107:9;-1:-1:-1;3032:9:9;;3028:574;;3106:14;3115:5;3106:14;;:::i;:::-;;;3149:12;3134:27;;3028:574;;;3204:7;3196:5;:15;3192:400;;;3286:1;;-1:-1:-1;3345:5:9;-1:-1:-1;3411:12:9;-1:-1:-1;3411:12:9;3345:5;3192:400;;;3505:5;3494:16;;;;3561;3546:31;;3192:400;2471:1137;;;;2299:1309;;;;;:::o;5267:223::-;5361:7;;:32;;-1:-1:-1;;;5361:32:9;;5387:4;5361:32;;;2889:51:12;5343:15:9;;5361:7;;;-1:-1:-1;;;;;5361:7:9;;:17;;2862:18:12;;5361:32:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5343:50;-1:-1:-1;5407:11:9;;5403:81;;5434:7;;:39;;-1:-1:-1;;;5434:39:9;;-1:-1:-1;;;;;18532:32:12;;;5434:39:9;;;18514:51:12;18581:18;;;18574:34;;;5434:7:9;;;;;;;;:16;;18487:18:12;;5434:39:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;11221:114:11:-;11287:12;:10;:12::i;:::-;-1:-1:-1;;;;;11273:26:11;:10;-1:-1:-1;;;;;11273:26:11;;:54;;;-1:-1:-1;11317:10:11;;-1:-1:-1;;;;;11317:10:11;11303;:24;11265:63;;;;;12423:778;12589:4;;-1:-1:-1;;;;;12589:4:11;12581:27;12573:68;;;;-1:-1:-1;;;12573:68:11;;20693:2:12;12573:68:11;;;20675:21:12;20732:2;20712:18;;;20705:30;20771;20751:18;;;20744:58;20819:18;;12573:68:11;20491:352:12;12573:68:11;12652:5;:24;;-1:-1:-1;;;;;;12652:24:11;-1:-1:-1;;;;;12652:24:11;;;;;;;;12700:13;;;-1:-1:-1;;;12700:13:11;;;;:11;;:13;;;;;;;;;;;;;;;12652:24;12700:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12686:4;:28;;-1:-1:-1;;;;;;12686:28:11;-1:-1:-1;;;;;12686:28:11;;;;;;;;;12724:43;;12741:6;-1:-1:-1;;12724:16:11;:43::i;:::-;12825:10;:24;;-1:-1:-1;;;;;12825:24:11;;;-1:-1:-1;;;;;;12825:24:11;;;;;;;12859:7;:18;;;;;;;;;;;12887:6;:16;;;;;;;;;;;;;;12963:7;12946:14;:24;13014:5;;:16;;;-1:-1:-1;;;13014:16:11;;;;: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:11;;-1:-1:-1;;;;;13137:7:11;;;13123:41;;;18514:51:12;;;;-1:-1:-1;;18581:18:12;;;18574:34;13123:5:11;;;;:13;;18487:18:12;;13123:41:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;12423:778;;;;:::o;10834:195::-;10911:10;;-1:-1:-1;;;;;10911:10:11;10897;:24;;:54;;;10939:12;:10;:12::i;3747:706:5:-;4166:23;4192:69;4220:4;4192:69;;;;;;;;;;;;;;;;;4200:5;-1:-1:-1;;;;;4192:27:5;;;:69;;;;;:::i;:::-;4275:17;;4166:95;;-1:-1:-1;4275:21:5;4271:176;;4370:10;4359:30;;;;;;;;;;;;:::i;:::-;4351:85;;;;-1:-1:-1;;;4351:85:5;;22597:2:12;4351:85:5;;;22579:21:12;22636:2;22616:18;;;22609:30;22675:34;22655:18;;;22648:62;-1:-1:-1;;;22726:18:12;;;22719:40;22776:19;;4351:85:5;22395:406:12;4960:446:6;5125:12;5182:5;5157:21;:30;;5149:81;;;;-1:-1:-1;;;5149:81:6;;23008:2:12;5149:81:6;;;22990:21:12;23047:2;23027:18;;;23020:30;23086:34;23066:18;;;23059:62;-1:-1:-1;;;23137:18:12;;;23130:36;23183:19;;5149:81:6;22806:402:12;5149:81:6;5241:12;5255:23;5282:6;-1:-1:-1;;;;;5282:11:6;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:6:o;588:104:8:-;646:7;676:1;672;:5;:13;;684:1;672:13;;;680:1;672:13;665:20;588:104;-1:-1:-1;;;588:104:8:o;7466:628:6:-;7646:12;7674:7;7670:418;;;7701:10;:17;7722:1;7701:22;7697:286;;-1:-1:-1;;;;;1465:19:6;;;7908:60;;;;-1:-1:-1;;;7908:60:6;;23707:2:12;7908:60:6;;;23689:21:12;23746:2;23726:18;;;23719:30;23785:31;23765:18;;;23758:59;23834:18;;7908:60:6;23505:353:12;7908:60:6;-1:-1:-1;8003:10:6;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:6;;;;;;;;:::i;14:131:12:-;-1:-1:-1;;;;;89:31:12;;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;402:250::-;487:1;497:113;511:6;508:1;505:13;497:113;;;587:11;;;581:18;568:11;;;561:39;533:2;526:10;497:113;;;-1:-1:-1;;644:1:12;626:16;;619:27;402:250::o;657:271::-;699:3;737:5;731:12;764:6;759:3;752:19;780:76;849:6;842:4;837:3;833:14;826:4;819:5;815:16;780:76;:::i;:::-;910:2;889:15;-1:-1:-1;;885:29:12;876:39;;;;917:4;872:50;;657:271;-1:-1:-1;;657:271:12:o;933:220::-;1082:2;1071:9;1064:21;1045:4;1102:45;1143:2;1132:9;1128:18;1120:6;1102:45;:::i;1158:127::-;1219:10;1214:3;1210:20;1207:1;1200:31;1250:4;1247:1;1240:15;1274:4;1271:1;1264:15;1290:247;1357:2;1351:9;1399:3;1387:16;;1433:18;1418:34;;1454:22;;;1415:62;1412:88;;;1480:18;;:::i;:::-;1516:2;1509:22;1290:247;:::o;1542:719::-;1585:5;1638:3;1631:4;1623:6;1619:17;1615:27;1605:55;;1656:1;1653;1646:12;1605:55;1692:6;1679:20;1718:18;1755:2;1751;1748:10;1745:36;;;1761:18;;:::i;:::-;1836:2;1830:9;1804:2;1890:13;;-1:-1:-1;;1886:22:12;;;1910:2;1882:31;1878:40;1866:53;;;1934:18;;;1954:22;;;1931:46;1928:72;;;1980:18;;:::i;:::-;2020:10;2016:2;2009:22;2055:2;2047:6;2040:18;2101:3;2094:4;2089:2;2081:6;2077:15;2073:26;2070:35;2067:55;;;2118:1;2115;2108:12;2067:55;2182:2;2175:4;2167:6;2163:17;2156:4;2148:6;2144:17;2131:54;2229:1;2222:4;2217:2;2209:6;2205:15;2201:26;2194:37;2249:6;2240:15;;;;;;1542:719;;;;:::o;2266:457::-;2344:6;2352;2405:2;2393:9;2384:7;2380:23;2376:32;2373:52;;;2421:1;2418;2411:12;2373:52;2460:9;2447:23;2479:31;2504:5;2479:31;:::i;:::-;2529:5;-1:-1:-1;2585:2:12;2570:18;;2557:32;2612:18;2601:30;;2598:50;;;2644:1;2641;2634:12;2598:50;2667;2709:7;2700:6;2689:9;2685:22;2667:50;:::i;:::-;2657:60;;;2266:457;;;;;:::o;2951:118::-;3037:5;3030:13;3023:21;3016:5;3013:32;3003:60;;3059:1;3056;3049:12;3074:241;3130:6;3183:2;3171:9;3162:7;3158:23;3154:32;3151:52;;;3199:1;3196;3189:12;3151:52;3238:9;3225:23;3257:28;3279:5;3257:28;:::i;3750:1024::-;3864:6;3872;3880;3888;3896;3904;3957:3;3945:9;3936:7;3932:23;3928:33;3925:53;;;3974:1;3971;3964:12;3925:53;4013:9;4000:23;4032:31;4057:5;4032:31;:::i;:::-;4082:5;-1:-1:-1;4139:2:12;4124:18;;4111:32;4152:33;4111:32;4152:33;:::i;:::-;4204:7;-1:-1:-1;4262:2:12;4247:18;;4234:32;4289:18;4278:30;;4275:50;;;4321:1;4318;4311:12;4275:50;4344;4386:7;4377:6;4366:9;4362:22;4344:50;:::i;:::-;4334:60;;;4446:2;4435:9;4431:18;4418:32;4459:33;4484:7;4459:33;:::i;:::-;4511:7;-1:-1:-1;4570:3:12;4555:19;;4542:33;4584;4542;4584;:::i;:::-;4636:7;-1:-1:-1;4695:3:12;4680:19;;4667:33;4709;4667;4709;:::i;:::-;4761:7;4751:17;;;3750:1024;;;;;;;;:::o;4971:180::-;5030:6;5083:2;5071:9;5062:7;5058:23;5054:32;5051:52;;;5099:1;5096;5089:12;5051:52;-1:-1:-1;5122:23:12;;4971:180;-1:-1:-1;4971:180:12:o;5338:592::-;5409:6;5417;5470:2;5458:9;5449:7;5445:23;5441:32;5438:52;;;5486:1;5483;5476:12;5438:52;5526:9;5513:23;5555:18;5596:2;5588:6;5585:14;5582:34;;;5612:1;5609;5602:12;5582:34;5650:6;5639:9;5635:22;5625:32;;5695:7;5688:4;5684:2;5680:13;5676:27;5666:55;;5717:1;5714;5707:12;5666:55;5757:2;5744:16;5783:2;5775:6;5772:14;5769:34;;;5799:1;5796;5789:12;5769:34;5844:7;5839:2;5830:6;5826:2;5822:15;5818:24;5815:37;5812:57;;;5865:1;5862;5855:12;5812:57;5896:2;5888:11;;;;;5918:6;;-1:-1:-1;5338:592:12;;-1:-1:-1;;;;5338:592:12:o;5935:671::-;6021:6;6029;6037;6045;6098:3;6086:9;6077:7;6073:23;6069:33;6066:53;;;6115:1;6112;6105:12;6066:53;6154:9;6141:23;6173:31;6198:5;6173:31;:::i;:::-;6223:5;-1:-1:-1;6280:2:12;6265:18;;6252:32;6293:33;6252:32;6293:33;:::i;:::-;6345:7;-1:-1:-1;6404:2:12;6389:18;;6376:32;6417:33;6376:32;6417:33;:::i;:::-;6469:7;-1:-1:-1;6528:2:12;6513:18;;6500:32;6541:33;6500:32;6541:33;:::i;:::-;5935:671;;;;-1:-1:-1;5935:671:12;;-1:-1:-1;;5935:671:12:o;7504:127::-;7565:10;7560:3;7556:20;7553:1;7546:31;7596:4;7593:1;7586:15;7620:4;7617:1;7610:15;7975:127;8036:10;8031:3;8027:20;8024:1;8017:31;8067:4;8064:1;8057:15;8091:4;8088:1;8081:15;8107:135;8146:3;8167:17;;;8164:43;;8187:18;;:::i;:::-;-1:-1:-1;8234:1:12;8223:13;;8107:135::o;8247:184::-;8317:6;8370:2;8358:9;8349:7;8345:23;8341:32;8338:52;;;8386:1;8383;8376:12;8338:52;-1:-1:-1;8409:16:12;;8247:184;-1:-1:-1;8247:184:12:o;8436:380::-;8515:1;8511:12;;;;8558;;;8579:61;;8633:4;8625:6;8621:17;8611:27;;8579:61;8686:2;8678:6;8675:14;8655:18;8652:38;8649:161;;8732:10;8727:3;8723:20;8720:1;8713:31;8767:4;8764:1;8757:15;8795:4;8792:1;8785:15;9162:251;9232:6;9285:2;9273:9;9264:7;9260:23;9256:32;9253:52;;;9301:1;9298;9291:12;9253:52;9333:9;9327:16;9352:31;9377:5;9352:31;:::i;9883:545::-;9985:2;9980:3;9977:11;9974:448;;;10021:1;10046:5;10042:2;10035:17;10091:4;10087:2;10077:19;10161:2;10149:10;10145:19;10142:1;10138:27;10132:4;10128:38;10197:4;10185:10;10182:20;10179:47;;;-1:-1:-1;10220:4:12;10179:47;10275:2;10270:3;10266:12;10263:1;10259:20;10253:4;10249:31;10239:41;;10330:82;10348:2;10341:5;10338:13;10330:82;;;10393:17;;;10374:1;10363:13;10330:82;;;10334:3;;;9883:545;;;:::o;10604:1352::-;10730:3;10724:10;10757:18;10749:6;10746:30;10743:56;;;10779:18;;:::i;:::-;10808:97;10898:6;10858:38;10890:4;10884:11;10858:38;:::i;:::-;10852:4;10808:97;:::i;:::-;10960:4;;11024:2;11013:14;;11041:1;11036:663;;;;11743:1;11760:6;11757:89;;;-1:-1:-1;11812:19:12;;;11806:26;11757:89;-1:-1:-1;;10561:1:12;10557:11;;;10553:24;10549:29;10539:40;10585:1;10581:11;;;10536:57;11859:81;;11006:944;;11036:663;9830:1;9823:14;;;9867:4;9854:18;;-1:-1:-1;;11072:20:12;;;11190:236;11204:7;11201:1;11198:14;11190:236;;;11293:19;;;11287:26;11272:42;;11385:27;;;;11353:1;11341:14;;;;11220:19;;11190:236;;;11194:3;11454:6;11445:7;11442:19;11439:201;;;11515:19;;;11509:26;-1:-1:-1;;11598:1:12;11594:14;;;11610:3;11590:24;11586:37;11582:42;11567:58;11552:74;;11439:201;-1:-1:-1;;;;;11686:1:12;11670:14;;;11666:22;11653:36;;-1:-1:-1;10604:1352:12:o;11961:317::-;-1:-1:-1;;;;;12138:32:12;;12120:51;;12207:2;12202;12187:18;;12180:30;;;-1:-1:-1;;12227:45:12;;12253:18;;12245:6;12227:45;:::i;12283:779::-;12385:6;12438:3;12426:9;12417:7;12413:23;12409:33;12406:53;;;12455:1;12452;12445:12;12406:53;12481:17;;:::i;:::-;12527:9;12521:16;12514:5;12507:31;12591:2;12580:9;12576:18;12570:25;12565:2;12558:5;12554:14;12547:49;12649:2;12638:9;12634:18;12628:25;12623:2;12616:5;12612:14;12605:49;12707:2;12696:9;12692:18;12686:25;12681:2;12674:5;12670:14;12663:49;12766:3;12755:9;12751:19;12745:26;12739:3;12732:5;12728:15;12721:51;12826:3;12815:9;12811:19;12805:26;12799:3;12792:5;12788:15;12781:51;12886:3;12875:9;12871:19;12865:26;12859:3;12852:5;12848:15;12841:51;12946:3;12935:9;12931:19;12925:26;12919:3;12912:5;12908:15;12901:51;12971:3;13027:2;13016:9;13012:18;13006:25;13001:2;12994:5;12990:14;12983:49;;13051:5;13041:15;;;12283:779;;;;:::o;13737:128::-;13804:9;;;13825:11;;;13822:37;;;13839:18;;:::i;14662:245::-;14729:6;14782:2;14770:9;14761:7;14757:23;14753:32;14750:52;;;14798:1;14795;14788:12;14750:52;14830:9;14824:16;14849:28;14871:5;14849:28;:::i;15649:1206::-;15773:18;15768:3;15765:27;15762:53;;;15795:18;;:::i;:::-;15824:94;15914:3;15874:38;15906:4;15900:11;15874:38;:::i;:::-;15868:4;15824:94;:::i;:::-;15944:1;15969:2;15964:3;15961:11;15986:1;15981:616;;;;16641:1;16658:3;16655:93;;;-1:-1:-1;16714:19:12;;;16701:33;16655:93;-1:-1:-1;;10561:1:12;10557:11;;;10553:24;10549:29;10539:40;10585:1;10581:11;;;10536:57;16761:78;;15954:895;;15981:616;9830:1;9823:14;;;9867:4;9854:18;;-1:-1:-1;;16017:17:12;;;16118:9;16140:229;16154:7;16151:1;16148:14;16140:229;;;16243:19;;;16230:33;16215:49;;16350:4;16335:20;;;;16303:1;16291:14;;;;16170:12;16140:229;;;16144:3;16397;16388:7;16385:16;16382:159;;;16521:1;16517:6;16511:3;16505;16502:1;16498:11;16494:21;16490:34;16486:39;16473:9;16468:3;16464:19;16451:33;16447:79;16439:6;16432:95;16382:159;;;16584:1;16578:3;16575:1;16571:11;16567:19;16561:4;16554:33;15954:895;;15649:1206;;;:::o;16860:390::-;17019:2;17008:9;17001:21;17058:6;17053:2;17042:9;17038:18;17031:34;17115:6;17107;17102:2;17091:9;17087:18;17074:48;17171:1;17142:22;;;17166:2;17138:31;;;17131:42;;;;17234:2;17213:15;;;-1:-1:-1;;17209:29:12;17194:45;17190:54;;16860:390;-1:-1:-1;16860:390:12:o;18898:125::-;18963:9;;;18984:10;;;18981:36;;;18997:18;;:::i;20848:422::-;20937:1;20980:5;20937:1;20994:270;21015:7;21005:8;21002:21;20994:270;;;21074:4;21070:1;21066:6;21062:17;21056:4;21053:27;21050:53;;;21083:18;;:::i;:::-;21133:7;21123:8;21119:22;21116:55;;;21153:16;;;;21116:55;21232:22;;;;21192:15;;;;20994:270;;;20998:3;20848:422;;;;;:::o;21275:806::-;21324:5;21354:8;21344:80;;-1:-1:-1;21395:1:12;21409:5;;21344:80;21443:4;21433:76;;-1:-1:-1;21480:1:12;21494:5;;21433:76;21525:4;21543:1;21538:59;;;;21611:1;21606:130;;;;21518:218;;21538:59;21568:1;21559:10;;21582:5;;;21606:130;21643:3;21633:8;21630:17;21627:43;;;21650:18;;:::i;:::-;-1:-1:-1;;21706:1:12;21692:16;;21721:5;;21518:218;;21820:2;21810:8;21807:16;21801:3;21795:4;21792:13;21788:36;21782:2;21772:8;21769:16;21764:2;21758:4;21755:12;21751:35;21748:77;21745:159;;;-1:-1:-1;21857:19:12;;;21889:5;;21745:159;21936:34;21961:8;21955:4;21936:34;:::i;:::-;22006:6;22002:1;21998:6;21994:19;21985:7;21982:32;21979:58;;;22017:18;;:::i;:::-;22055:20;;21275:806;-1:-1:-1;;;21275:806:12:o;22086:131::-;22146:5;22175:36;22202:8;22196:4;22175:36;:::i;22222:168::-;22295:9;;;22326;;22343:15;;;22337:22;;22323:37;22313:71;;22364:18;;:::i;23213:287::-;23342:3;23380:6;23374:13;23396:66;23455:6;23450:3;23443:4;23435:6;23431:17;23396:66;:::i;:::-;23478:16;;;;;23213:287;-1:-1:-1;;23213:287:12:o
Swarm Source
ipfs://fccd0f92bf4e816949da27d789e7b4c73aa71d7c44a4fa27090fb75e5fd01113
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.