Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Advanced mode: Intended for advanced users or developers and will display all Internal Transactions including zero value transfers.
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
|||
|---|---|---|---|---|---|---|---|---|
| Withdraw BB | 23810990 | 134 days ago | 0 ETH | |||||
| Withdraw BB | 23746592 | 143 days ago | 0 ETH | |||||
| Withdraw AA | 23684635 | 151 days ago | 0 ETH | |||||
| Deposit AA | 23684627 | 151 days ago | 0 ETH | |||||
| Withdraw BB | 22668259 | 293 days ago | 0 ETH | |||||
| Withdraw BB | 22357975 | 337 days ago | 0 ETH | |||||
| Withdraw BB | 22102627 | 372 days ago | 0 ETH | |||||
| Withdraw BB | 21980784 | 389 days ago | 0 ETH | |||||
| Deposit BB | 21956209 | 393 days ago | 0 ETH | |||||
| Withdraw BB | 21933122 | 396 days ago | 0 ETH | |||||
| Withdraw AA | 21719722 | 426 days ago | 0 ETH | |||||
| Withdraw AA | 21719690 | 426 days ago | 0 ETH | |||||
| Withdraw BB | 21638749 | 437 days ago | 0 ETH | |||||
| Harvest | 21582512 | 445 days ago | 0 ETH | |||||
| Deposit BB | 21582047 | 445 days ago | 0 ETH | |||||
| Deposit BB | 21508651 | 455 days ago | 0 ETH | |||||
| Deposit BB | 21507515 | 456 days ago | 0 ETH | |||||
| Harvest | 21470205 | 461 days ago | 0 ETH | |||||
| Deposit BB | 21469092 | 461 days ago | 0 ETH | |||||
| Harvest | 21430912 | 466 days ago | 0 ETH | |||||
| Harvest | 21387078 | 472 days ago | 0 ETH | |||||
| Deposit BB | 21386190 | 473 days ago | 0 ETH | |||||
| Harvest | 21332444 | 480 days ago | 0 ETH | |||||
| Withdraw AA | 20746600 | 562 days ago | 0 ETH | |||||
| Withdraw AA | 20641466 | 577 days ago | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
IdleCDOGearboxVariant
Compiler Version
v0.8.10+commit.fc410830
Optimization Enabled:
Yes with 170 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.10;
import {IdleCDO} from "./IdleCDO.sol";
/// @title IdleCDO variant for gearbox passive lending.
/// @notice strategyToken is set to the strategy itself which tokenizes the staked position (sdTokens) to farm GEAR
contract IdleCDOGearboxVariant is IdleCDO {
function _additionalInit() internal override {
strategyToken = strategy;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
function __Pausable_init() internal onlyInitializing {
__Pausable_init_unchained();
}
function __Pausable_init_unchained() internal onlyInitializing {
_paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuardUpgradeable is Initializable {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
function __ReentrancyGuard_init() internal onlyInitializing {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal onlyInitializing {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/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 IERC20PermitUpgradeable {
/**
* @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 (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20Upgradeable {
/**
* @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.9.3) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20Upgradeable.sol";
import "../extensions/IERC20PermitUpgradeable.sol";
import "../../../utils/AddressUpgradeable.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20Upgradeable {
using AddressUpgradeable for address;
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
function safePermit(
IERC20PermitUpgradeable 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(IERC20Upgradeable token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.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].
*
* The default value of {decimals} is 18. To change this, you should override
* this function so it returns a different value.
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the default value returned by this function, unless
* it's overridden.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/
function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/
function _transfer(address from, address to, uint256 amount) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
// Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
// decrementing then incrementing.
_balances[to] += amount;
}
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
unchecked {
// Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
_balances[account] += amount;
}
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
// Overflow not possible: amount <= accountBalance <= totalSupply.
_totalSupply -= amount;
}
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `amount`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/
function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
}// 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);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.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 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;
}
}pragma solidity >=0.6.2;
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountA, uint amountB);
function removeLiquidityETHWithPermit(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}pragma solidity >=0.6.2;
import './IUniswapV2Router01.sol';
interface IUniswapV2Router02 is IUniswapV2Router01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
/// @title Callback for IUniswapV3PoolActions#swap
/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface
interface IUniswapV3SwapCallback {
/// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.
/// @dev In the implementation you must pay the pool tokens owed for the swap.
/// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.
/// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.
/// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by
/// the end of the swap. If positive, the callback must send that amount of token0 to the pool.
/// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by
/// the end of the swap. If positive, the callback must send that amount of token1 to the pool.
/// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call
function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata data
) external;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;
import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';
/// @title Router token swapping functionality
/// @notice Functions for swapping tokens via Uniswap V3
interface ISwapRouter is IUniswapV3SwapCallback {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another token
/// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata
/// @return amountOut The amount of the received token
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata
/// @return amountOut The amount of the received token
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
uint160 sqrtPriceLimitX96;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another token
/// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata
/// @return amountIn The amount of the input token
function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata
/// @return amountIn The amount of the input token
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}//SPDX-License-Identifier: Apache 2.0
pragma solidity 0.8.10;
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
/// @notice This abstract contract is used to add an updatable limit on the total value locked
/// that the contract can have. It also have an emergency method that allows the owner to pull
/// funds into predefined recovery address
/// @dev Inherit this contract and add the _guarded method to the child contract
abstract contract GuardedLaunchUpgradable is Initializable, OwnableUpgradeable, ReentrancyGuardUpgradeable {
using SafeERC20Upgradeable for IERC20Upgradeable;
// ERROR MESSAGES:
// 0 = is 0
// 1 = already initialized
// 2 = Contract limit reached
// TVL limit in underlying value
uint256 public limit;
// recovery address
address public governanceRecoveryFund;
/// @param _limit TVL limit. (0 means unlimited)
/// @param _governanceRecoveryFund recovery address
/// @param _owner owner address
function __GuardedLaunch_init(uint256 _limit, address _governanceRecoveryFund, address _owner) internal {
require(_governanceRecoveryFund != address(0), '0');
require(_owner != address(0), '0');
// Initialize inherited contracts
OwnableUpgradeable.__Ownable_init();
ReentrancyGuardUpgradeable.__ReentrancyGuard_init();
// Initialize state variables
limit = _limit;
governanceRecoveryFund = _governanceRecoveryFund;
// Transfer ownership
transferOwnership(_owner);
}
/// @notice this check should be called inside the child contract on deposits to check that the
/// TVL didn't exceed a threshold
/// @param _amount new amount to deposit
function _guarded(uint256 _amount) internal view {
uint256 _limit = limit;
if (_limit == 0) {
return;
}
require(getContractValue() + _amount <= _limit, '2');
}
/// @dev Check that the second function is not called in the same tx from the same tx.origin
function _checkOnlyOwner() internal view {
require(owner() == msg.sender, '6');
}
/// @notice abstract method, should return the TVL in underlyings
function getContractValue() public virtual view returns (uint256);
/// @notice set contract TVL limit
/// @param _limit limit in underlying value, 0 means no limit
function _setLimit(uint256 _limit) external {
_checkOnlyOwner();
limit = _limit;
}
/// @notice Emergency method, tokens gets transferred to the governanceRecoveryFund address
/// @param _token address of the token to transfer
/// @param _value amount to transfer
function transferToken(address _token, uint256 _value) external {
_checkOnlyOwner();
IERC20Upgradeable(_token).safeTransfer(governanceRecoveryFund, _value);
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.10;
import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
import '@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol';
import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import "./interfaces/IIdleCDOStrategy.sol";
import "./interfaces/IERC20Detailed.sol";
import "./GuardedLaunchUpgradable.sol";
import "./IdleCDOTranche.sol";
import "./IdleCDOStorage.sol";
/// @title A perpetual tranche implementation
/// @author Idle Labs Inc.
/// @notice More info and high level overview in the README
/// @dev The contract is upgradable, to add storage slots, create IdleCDOStorageVX and inherit from IdleCDOStorage, then update the definitaion below
contract IdleCDO is PausableUpgradeable, GuardedLaunchUpgradable, IdleCDOStorage {
using SafeERC20Upgradeable for IERC20Detailed;
// ERROR MESSAGES:
// 0 = is 0
// 1 = already initialized
// 2 = Contract limit reached
// 3 = Tranche withdraw not allowed (Paused or in shutdown)
// 4 = Default, wait shutdown
// 5 = Amount too low
// 6 = Not authorized
// 7 = Amount too high
// 8 = Same block
// 9 = Invalid
// Used to prevent initialization of the implementation contract
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
token = address(1);
}
// ###################
// Initializer
// ###################
/// @notice can only be called once
/// @dev Initialize the upgradable contract
/// @param _limit contract value limit, can be 0
/// @param _guardedToken underlying token
/// @param _governanceFund address where funds will be sent in case of emergency
/// @param _owner guardian address (can pause, unpause and call emergencyShutdown)
/// @param _rebalancer rebalancer address
/// @param _strategy strategy address
/// @param _trancheAPRSplitRatio trancheAPRSplitRatio value
/// @param // deprecated
/// @param // deprecated _incentiveTokens array of addresses for incentive tokens
function initialize(
uint256 _limit, address _guardedToken, address _governanceFund, address _owner, // GuardedLaunch args
address _rebalancer,
address _strategy,
uint256 _trancheAPRSplitRatio, // for AA tranches, so eg 10000 means 10% interest to AA and 90% BB
uint256, // Deprecated
address[] memory // Deprecated
) external initializer {
require(token == address(0), '1');
require(_rebalancer != address(0), '0');
require(_strategy != address(0), '0');
require(_guardedToken != address(0), '0');
require( _trancheAPRSplitRatio <= FULL_ALLOC, '7');
// Initialize contracts
PausableUpgradeable.__Pausable_init();
// check for _governanceFund and _owner != address(0) are inside GuardedLaunchUpgradable
GuardedLaunchUpgradable.__GuardedLaunch_init(_limit, _governanceFund, _owner);
// Deploy Tranches tokens
address _strategyToken = IIdleCDOStrategy(_strategy).strategyToken();
// get strategy token symbol (eg. idleDAI)
string memory _symbol = IERC20Detailed(_strategyToken).symbol();
// create tranche tokens (concat strategy token symbol in the name and symbol of the tranche tokens)
AATranche = address(new IdleCDOTranche(_concat(string("IdleCDO AA Tranche - "), _symbol), _concat(string("AA_"), _symbol)));
BBTranche = address(new IdleCDOTranche(_concat(string("IdleCDO BB Tranche - "), _symbol), _concat(string("BB_"), _symbol)));
// Set CDO params
token = _guardedToken;
strategy = _strategy;
strategyToken = _strategyToken;
rebalancer = _rebalancer;
trancheAPRSplitRatio = _trancheAPRSplitRatio;
uint256 _oneToken = 10**(IERC20Detailed(_guardedToken).decimals());
oneToken = _oneToken;
uniswapRouterV2 = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
weth = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
// incentiveTokens = _incentiveTokens; [DEPRECATED]
priceAA = _oneToken;
priceBB = _oneToken;
unlentPerc = 2000; // 2%
// # blocks, after an harvest, during which harvested rewards gets progressively unlocked
releaseBlocksPeriod = 6400; // about 1 day
// Set flags
allowAAWithdraw = true;
allowBBWithdraw = true;
revertIfTooLow = true;
// skipDefaultCheck = false is the default value
// Set allowance for strategy
_allowUnlimitedSpend(_guardedToken, _strategy);
_allowUnlimitedSpend(_strategyToken, _strategy);
// Save current strategy price
lastStrategyPrice = _strategyPrice();
// Fee params
fee = 15000; // 15% performance fee
feeReceiver = address(0xFb3bD022D5DAcF95eE28a6B07825D4Ff9C5b3814); // treasury multisig
guardian = _owner;
// feeSplit = 0; // default all to feeReceiver
isAYSActive = true; // adaptive yield split
minAprSplitAYS = AA_RATIO_LIM_DOWN; // AA tranche will get min 50% of the yield
maxDecreaseDefault = 5000; // 5% decrease for triggering a default
_additionalInit();
}
/// @notice used by child contracts (cdo variants) if anything needs to be done on/after init
function _additionalInit() internal virtual {}
// ###############
// Public methods
// ###############
/// @notice pausable
/// @dev msg.sender should approve this contract first to spend `_amount` of `token`
/// @param _amount amount of `token` to deposit
/// @return AA tranche tokens minted
function depositAA(uint256 _amount) external returns (uint256) {
return _deposit(_amount, AATranche, address(0));
}
/// @notice pausable in _deposit
/// @dev msg.sender should approve this contract first to spend `_amount` of `token`
/// @param _amount amount of `token` to deposit
/// @return BB tranche tokens minted
function depositBB(uint256 _amount) external returns (uint256) {
return _deposit(_amount, BBTranche, address(0));
}
/// @notice pausable
/// @dev msg.sender should approve this contract first to spend `_amount` of `token`
/// @param _amount amount of `token` to deposit
/// @param _referral address of the referral
/// @return AA tranche tokens minted
function depositAARef(uint256 _amount, address _referral) external returns (uint256) {
return _deposit(_amount, AATranche, _referral);
}
/// @notice pausable in _deposit
/// @dev msg.sender should approve this contract first to spend `_amount` of `token`
/// @param _amount amount of `token` to deposit
/// @param _referral address of the referral
/// @return BB tranche tokens minted
function depositBBRef(uint256 _amount, address _referral) external returns (uint256) {
return _deposit(_amount, BBTranche, _referral);
}
/// @notice pausable in _deposit
/// @param _amount amount of AA tranche tokens to burn
/// @return underlying tokens redeemed
function withdrawAA(uint256 _amount) external returns (uint256) {
require(!paused() || allowAAWithdraw, '3');
return _withdraw(_amount, AATranche);
}
/// @notice pausable
/// @param _amount amount of BB tranche tokens to burn
/// @return underlying tokens redeemed
function withdrawBB(uint256 _amount) external returns (uint256) {
require(!paused() || allowBBWithdraw, '3');
return _withdraw(_amount, BBTranche);
}
// ###############
// Views
// ###############
/// @param _tranche tranche address
/// @return tranche price, in underlyings, at the last interaction (not considering interest earned
/// since last interaction)
function tranchePrice(address _tranche) external view returns (uint256) {
return _tranchePrice(_tranche);
}
/// @notice calculates the current net TVL (in `token` terms)
/// @dev unclaimed rewards (gov tokens) and `unclaimedFees` are not counted.
/// Harvested rewards are counted only if enough blocks have passed (`_lockedRewards`)
function getContractValue() public override view returns (uint256) {
address _strategyToken = strategyToken;
uint256 strategyTokenDecimals = IERC20Detailed(_strategyToken).decimals();
// TVL is the sum of unlent balance in the contract + the balance in lending - harvested but locked rewards - unclaimedFees
// Balance in lending is the value of the interest bearing assets (strategyTokens) in this contract
// TVL = (strategyTokens * strategy token price) + unlent balance - lockedRewards - unclaimedFees
return (_contractTokenBalance(_strategyToken) * _strategyPrice() / (10**(strategyTokenDecimals))) +
_contractTokenBalance(token) -
_lockedRewards() -
unclaimedFees;
}
/// @param _tranche tranche address
/// @return actual apr given current ratio between AA and BB tranches
function getApr(address _tranche) external view returns (uint256) {
return _getApr(_tranche, _getAARatio(false));
}
/// @notice calculates the current AA tranches ratio
/// @dev _virtualBalance is used to have a more accurate/recent value for the AA ratio
/// because it calculates the balance after splitting the accrued interest since the
/// last depositXX/withdrawXX/harvest
/// @return AA tranches ratio (in underlying value) considering all interest
function getCurrentAARatio() external view returns (uint256) {
return _getAARatio(false);
}
/// @notice calculates the current tranches price considering the interest/loss that is yet to be splitted
/// ie the interest/loss generated since the last update of priceAA and priceBB (done on depositXX/withdrawXX/harvest)
/// @param _tranche address of the requested tranche
/// @return _virtualPrice tranche price considering all interest/losses
function virtualPrice(address _tranche) public virtual view returns (uint256 _virtualPrice) {
// get both NAVs, because we need the total NAV anyway
uint256 _lastNAVAA = lastNAVAA;
uint256 _lastNAVBB = lastNAVBB;
(_virtualPrice, ) = _virtualPriceAux(
_tranche,
getContractValue(), // nav
_lastNAVAA + _lastNAVBB, // lastNAV
_tranche == AATranche ? _lastNAVAA : _lastNAVBB, // lastTrancheNAV
trancheAPRSplitRatio
);
}
/// @notice [DEPRECATED]
/// @return array with addresses of incentiveTokens (can be empty)
function getIncentiveTokens() external view returns (address[] memory) {
return incentiveTokens;
}
// ###############
// Internal
// ###############
/// @notice method used to check if depositor has enough stkIDLE per unit of underlying to access the vault.
/// This can be used to give priority access to new vaults to stkIDLE holders.
/// @dev This check is only intended for "regular" users as it does not strictly enforce the _stkIDLEPerUnderlying
/// ratio (eg: deposit+transfer). This will be mitigated by the fee rebate mechanism (airdrop) as otherwise those
/// rebates will be lost.
/// @param _amount amount of underlying to deposit
function _checkStkIDLEBal(address _tranche, uint256 _amount) internal view {
uint256 _stkIDLEPerUnderlying = stkIDLEPerUnderlying;
// check if stkIDLE requirement is active for _tranche
if (_stkIDLEPerUnderlying == 0 ||
(_tranche == BBTranche && BBStaking == address(0)) ||
(_tranche == AATranche && AAStaking == address(0))) {
return;
}
uint256 trancheBal = IERC20Detailed(_tranche).balanceOf(msg.sender);
// We check if sender deposited in the same tranche previously and add the bal to _amount
uint256 bal = _amount + (trancheBal > 0 ? (trancheBal * _tranchePrice(_tranche) / ONE_TRANCHE_TOKEN) : 0);
require(
IERC20(STK_IDLE).balanceOf(msg.sender) >=
bal * _stkIDLEPerUnderlying / oneToken,
'7'
);
}
/// @notice method used to deposit `token` and mint tranche tokens
/// Ideally users should deposit right after an `harvest` call to maximize profit
/// @dev this contract must be approved to spend at least _amount of `token` before calling this method
/// automatically reverts on lending provider default (_strategyPrice decreased)
/// @param _amount amount of underlyings (`token`) to deposit
/// @param _tranche tranche address
/// @param _referral referral address
/// @return _minted number of tranche tokens minted
function _deposit(uint256 _amount, address _tranche, address _referral) internal virtual whenNotPaused returns (uint256 _minted) {
if (_amount == 0) {
return _minted;
}
// check that we are not depositing more than the contract available limit
_guarded(_amount);
// set _lastCallerBlock hash
_updateCallerBlock();
// check if _strategyPrice decreased
_checkDefault();
// interest accrued since last depositXX/withdrawXX/harvest is splitted between AA and BB
// according to trancheAPRSplitRatio. NAVs of AA and BB are updated and tranche
// prices adjusted accordingly
_updateAccounting();
// check if depositor has enough stkIDLE for the amount to be deposited
_checkStkIDLEBal(_tranche, _amount);
// get underlyings from sender
address _token = token;
uint256 _preBal = _contractTokenBalance(_token);
IERC20Detailed(_token).safeTransferFrom(msg.sender, address(this), _amount);
// mint tranche tokens according to the current tranche price
_minted = _mintShares(_contractTokenBalance(_token) - _preBal, msg.sender, _tranche);
// update trancheAPRSplitRatio
_updateSplitRatio(_getAARatio(true));
if (_referral != address(0)) {
emit Referral(_amount, _referral);
}
}
/// @notice this method is called on depositXX/withdrawXX/harvest and
/// updates the accounting of the contract and effectively splits the yield/loss between the
/// AA and BB tranches
/// @dev this method:
/// - update tranche prices (priceAA and priceBB)
/// - update net asset value for both tranches (lastNAVAA and lastNAVBB)
/// - update fee accounting (unclaimedFees)
function _updateAccounting() internal virtual {
uint256 _lastNAVAA = lastNAVAA;
uint256 _lastNAVBB = lastNAVBB;
uint256 _lastNAV = _lastNAVAA + _lastNAVBB;
uint256 nav = getContractValue();
uint256 _aprSplitRatio = trancheAPRSplitRatio;
// If gain is > 0, then collect some fees in `unclaimedFees`
if (nav > _lastNAV) {
unclaimedFees += (nav - _lastNAV) * fee / FULL_ALLOC;
}
(uint256 _priceAA, int256 _totalAAGain) = _virtualPriceAux(AATranche, nav, _lastNAV, _lastNAVAA, _aprSplitRatio);
(uint256 _priceBB, int256 _totalBBGain) = _virtualPriceAux(BBTranche, nav, _lastNAV, _lastNAVBB, _aprSplitRatio);
lastNAVAA = uint256(int256(_lastNAVAA) + _totalAAGain);
// if we have a loss and it's gte last junior NAV we trigger a default
if (_totalBBGain < 0 && -_totalBBGain >= int256(_lastNAVBB)) {
// revert with 'default' error (4) if skipDefaultCheck is false, as seniors will have a loss too not covered.
// `updateAccounting` should be manually called to distribute loss
require(skipDefaultCheck, "4");
// This path will be called when a default happens and guardian calls
// `updateAccounting` after setting skipDefaultCheck or when skipDefaultCheck is already set to true
lastNAVBB = 0;
// if skipDefaultCheck is set to true prior a default (eg because AA is used as collateral and needs to be liquid),
// emergencyShutdown won't prevent the current deposit/redeem (the one that called this _updateAccounting) and is
// still correct because:
// - depositBB will revert as priceBB is 0
// - depositAA won't revert (unless the loss is 100% of TVL) and user will get
// correct number of share at a priceAA already post junior default
// - withdrawBB will redeem 0 and burn BB tokens because priceBB is 0
// - withdrawAA will redeem the correct amount of underlyings post junior default
// We pass true as we still want AA to be redeemable in any case even after a junior default
_emergencyShutdown(true);
} else {
// we add the gain to last saved NAV
lastNAVBB = uint256(int256(_lastNAVBB) + _totalBBGain);
}
priceAA = _priceAA;
priceBB = _priceBB;
}
/// @notice calculates the NAV for a tranche considering the interest that is yet to be splitted
/// @param _tranche address of the requested tranche
/// @return net asset value, in underlying tokens, for _tranche considering all nav
function _virtualBalance(address _tranche) internal view returns (uint256) {
// balance is: tranche supply * virtual tranche price
return IdleCDOTranche(_tranche).totalSupply() * virtualPrice(_tranche) / ONE_TRANCHE_TOKEN;
}
/// @notice calculates the NAV for a tranche without considering the interest that is yet to be splitted
/// @param _tranche address of the requested tranche
/// @return net asset value, in underlying tokens, for _tranche
function _instantBalance(address _tranche) internal view returns (uint256) {
return IdleCDOTranche(_tranche).totalSupply() * _tranchePrice(_tranche) / ONE_TRANCHE_TOKEN;
}
/// @notice calculates the current tranches price considering the interest/loss that is yet to be splitted and the
/// total gain/loss for a specific tranche
/// @dev Main scenarios covered:
/// - if there is a loss on the lending protocol (ie strategy price decrease) up to maxDecreaseDefault (_checkDefault method), the loss is
/// - totally absorbed by junior holders if they have enough TVL and deposits/redeems work as normal
/// - otherwise a 'default' error (4) is raised and deposits/redeems are blocked
/// - if there is a loss on the lending protocol (ie strategy price decrease) more than maxDecreaseDefault all deposits and redeems
/// are blocked and a 'default' error (4) is raised
/// - if there is a loss somewhere not in the lending protocol (ie in our contracts) and the TVL decreases then the same process as above
/// applies, the only difference is that maxDecreaseDefault is not considered
/// In any case, once a loss happens, it only gets accounted when new deposits/redeems are made, but those are blocked.
/// For this reason a protected updateAccounting method has been added which should be used to distributed the loss after a default event
/// @param _tranche address of the requested tranche
/// @param _nav current NAV
/// @param _lastNAV last saved NAV
/// @param _lastTrancheNAV last saved tranche NAV
/// @param _trancheAPRSplitRatio APR split ratio for AA tranche
/// @return _virtualPrice tranche price considering all interest
/// @return _totalTrancheGain (int256) tranche gain/loss since last update
function _virtualPriceAux(
address _tranche,
uint256 _nav,
uint256 _lastNAV,
uint256 _lastTrancheNAV,
uint256 _trancheAPRSplitRatio
) internal virtual view returns (uint256 _virtualPrice, int256 _totalTrancheGain) {
// Check if there are tranche holders
uint256 trancheSupply = IdleCDOTranche(_tranche).totalSupply();
if (_lastNAV == 0 || trancheSupply == 0) {
return (oneToken, 0);
}
// In order to correctly split the interest generated between AA and BB tranche holders
// (according to the trancheAPRSplitRatio) we need to know how much interest/loss we gained
// since the last price update (during a depositXX/withdrawXX/harvest)
// To do that we need to get the current value of the assets in this contract
// and the last saved one (always during a depositXX/withdrawXX/harvest)
// Calculate the total gain/loss
int256 totalGain = int256(_nav) - int256(_lastNAV);
// If there is no gain/loss return the current price
if (totalGain == 0) {
return (_tranchePrice(_tranche), 0);
}
// Remove performance fee for gains
if (totalGain > 0) {
totalGain -= totalGain * int256(fee) / int256(FULL_ALLOC);
}
address _AATranche = AATranche;
address _BBTranche = BBTranche;
bool _isAATranche = _tranche == _AATranche;
// Get the supply of the other tranche and
// if it's 0 then give all gain to the current `_tranche` holders
if (IdleCDOTranche(_isAATranche ? _BBTranche : _AATranche).totalSupply() == 0) {
_totalTrancheGain = totalGain;
} else {
// if we gained something or the loss is between 0 and lossToleranceBps then we socialize the gain/loss
if (totalGain > 0) {
// Split the net gain, according to _trancheAPRSplitRatio, with precision loss favoring the AA tranche.
int256 totalBBGain = totalGain * int256(FULL_ALLOC - _trancheAPRSplitRatio) / int256(FULL_ALLOC);
// The new NAV for the tranche is old NAV + total gain for the tranche
_totalTrancheGain = _isAATranche ? (totalGain - totalBBGain) : totalBBGain;
} else if (uint256(-totalGain) <= (lossToleranceBps * _lastNAV) / FULL_ALLOC) {
// Split the loss, according to TVL ratio instead of _trancheAPRSplitRatio (loss socialized between all tranches)
uint256 _lastNAVBB = lastNAVBB;
int256 totalBBLoss = totalGain * int256(_lastNAVBB) / int256(lastNAVAA + _lastNAVBB);
// The new NAV for the tranche is old NAV - loss for the tranche
_totalTrancheGain = _isAATranche ? (totalGain - totalBBLoss) : totalBBLoss;
} else { // totalGain is negative here
// Redirect the whole loss (which should be < maxDecreaseDefault) to junior holders
int256 _juniorTVL = int256(_isAATranche ? _lastNAV - _lastTrancheNAV : _lastTrancheNAV);
int256 _newJuniorTVL = _juniorTVL + totalGain;
// if junior holders have enough TVL to cover
if (_newJuniorTVL > 0) {
// then juniors get all loss (totalGain) and senior gets 0 loss
_totalTrancheGain = _isAATranche ? int256(0) : totalGain;
} else {
// otherwise all loss minus junior tvl to senior
if (!_isAATranche) {
// juniors have no more claims, price is set to 0, gain is set to -juniorTVL
return (0, -_juniorTVL);
}
// seniors get the loss - old junior TVL
_totalTrancheGain = _newJuniorTVL;
}
}
}
// Split the new NAV (_lastTrancheNAV + _totalTrancheGain) per tranche token
_virtualPrice = uint256(int256(_lastTrancheNAV) + _totalTrancheGain) * ONE_TRANCHE_TOKEN / trancheSupply;
}
/// @notice mint tranche tokens and updates tranche last NAV
/// @param _amount, in underlyings, to convert in tranche tokens
/// @param _to receiver address of the newly minted tranche tokens
/// @param _tranche tranche address
/// @return _minted number of tranche tokens minted
function _mintShares(uint256 _amount, address _to, address _tranche) internal virtual returns (uint256 _minted) {
// calculate # of tranche token to mint based on current tranche price: _amount / tranchePrice
_minted = _amount * ONE_TRANCHE_TOKEN / _tranchePrice(_tranche);
IdleCDOTranche(_tranche).mint(_to, _minted);
// update NAV with the _amount of underlyings added
if (_tranche == AATranche) {
lastNAVAA += _amount;
} else {
lastNAVBB += _amount;
}
}
/// @notice convert fees (`unclaimedFees`) in AA tranche tokens
/// @dev this will be called only during harvests
function _depositFees() internal {
uint256 _amount = unclaimedFees;
if (_amount != 0) {
// mint tranches tokens (always AA) to this contract
_mintShares(_amount, feeReceiver, AATranche);
// reset unclaimedFees counter
unclaimedFees = 0;
// update trancheAPRSplitRatio using instant balance
_updateSplitRatio(_getAARatio(true));
}
}
/// @notice It allows users to burn their tranche token and redeem their principal + interest back
/// @dev automatically reverts on lending provider default (_strategyPrice decreased).
/// @param _amount in tranche tokens
/// @param _tranche tranche address
/// @return toRedeem number of underlyings redeemed
function _withdraw(uint256 _amount, address _tranche) virtual internal nonReentrant returns (uint256 toRedeem) {
// check if a deposit is made in the same block from the same user
_checkSameTx();
// check if _strategyPrice decreased
_checkDefault();
// accrue interest to tranches and updates tranche prices
_updateAccounting();
// redeem all user balance if 0 is passed as _amount
if (_amount == 0) {
_amount = IERC20Detailed(_tranche).balanceOf(msg.sender);
}
require(_amount != 0, '0');
address _token = token;
// get current available unlent balance
uint256 balanceUnderlying = _contractTokenBalance(_token);
// Calculate the amount to redeem
toRedeem = _amount * _tranchePrice(_tranche) / ONE_TRANCHE_TOKEN;
uint256 _want = toRedeem;
if (toRedeem > balanceUnderlying) {
// if the unlent balance is not enough we try to redeem what's missing directly from the strategy
// and then add it to the current unlent balance
// NOTE: A difference of up to 100 wei due to rounding is tolerated
toRedeem = _liquidate(toRedeem - balanceUnderlying, revertIfTooLow) + balanceUnderlying;
}
// burn tranche token
IdleCDOTranche(_tranche).burn(msg.sender, _amount);
// update NAV with the _amount of underlyings removed
if (_tranche == AATranche) {
lastNAVAA -= _want;
} else {
lastNAVBB -= _want;
}
// update trancheAPRSplitRatio
_updateSplitRatio(_getAARatio(true));
// send underlying to msg.sender. Keep this at the end of the function to avoid
// potential read only reentrancy on cdo variants that have hooks (eg with nfts)
IERC20Detailed(_token).safeTransfer(msg.sender, toRedeem);
}
/// @notice updates trancheAPRSplitRatio based on the current tranches TVL ratio between AA and BB
/// @dev the idea here is to limit the min and max APR that the senior tranche can get
function _updateSplitRatio(uint256 tvlAARatio) internal virtual {
uint256 _minSplit = minAprSplitAYS;
_minSplit = _minSplit == 0 ? AA_RATIO_LIM_DOWN : _minSplit;
if (isAYSActive) {
uint256 aux;
if (tvlAARatio >= AA_RATIO_LIM_UP) {
aux = AA_RATIO_LIM_UP;
} else if (tvlAARatio > _minSplit) {
aux = tvlAARatio;
} else {
aux = _minSplit;
}
trancheAPRSplitRatio = aux * tvlAARatio / FULL_ALLOC;
}
}
/// @notice calculates the current AA tranches ratio
/// @dev it does count accrued interest not yet split since last
/// depositXX/withdrawXX/harvest only if _instant flag is true
/// @param _instant if true, it returns the current ratio without accrued interest
/// @return AA tranches ratio (in underlying value) considering all interest
function _getAARatio(bool _instant) internal view returns (uint256) {
function(address) internal view returns (uint256) _getNAV =
_instant ? _instantBalance : _virtualBalance;
uint256 AABal = _getNAV(AATranche);
uint256 contractVal = AABal + _getNAV(BBTranche);
if (contractVal == 0) {
return 0;
}
// Current AA tranche split ratio = AABal * FULL_ALLOC / (AABal + BBBal)
return AABal * FULL_ALLOC / contractVal;
}
/// @dev check if _strategyPrice is decreased more than X% with X configurable since last update
/// and updates last saved strategy price
function _checkDefault() virtual internal {
uint256 currPrice = _strategyPrice();
if (!skipDefaultCheck) {
// calculate if % of decrease of strategyPrice is within maxDecreaseDefault
require(lastStrategyPrice * (FULL_ALLOC - maxDecreaseDefault) / FULL_ALLOC <= currPrice, "4");
}
lastStrategyPrice = currPrice;
}
/// @return strategy price, in underlyings
function _strategyPrice() internal view returns (uint256) {
return IIdleCDOStrategy(strategy).price();
}
/// @dev this should liquidate at least _amount of `token` from the lending provider or revertIfNeeded
/// @param _amount in underlying tokens
/// @param _revertIfNeeded flag whether to revert or not if the redeemed amount is not enough
/// @return _redeemedTokens number of underlyings redeemed
function _liquidate(uint256 _amount, bool _revertIfNeeded) internal virtual returns (uint256 _redeemedTokens) {
_redeemedTokens = IIdleCDOStrategy(strategy).redeemUnderlying(_amount);
if (_revertIfNeeded) {
uint256 _tolerance = liquidationTolerance;
if (_tolerance == 0) {
_tolerance = 100;
}
// keep `_tolerance` wei as margin for rounding errors
require(_redeemedTokens + _tolerance >= _amount, '5');
}
if (_redeemedTokens > _amount) {
_redeemedTokens = _amount;
}
}
/// @notice method used to sell `_rewardToken` for `_token` on uniswap
/// @param _rewardToken address of the token to sell
/// @param _path to buy
/// @param _amount of `_rewardToken` to sell
/// @param _minAmount min amount of `_token` to buy
/// @return _amount of _rewardToken sold
/// @return _amount received for the sell
function _sellReward(address _rewardToken, bytes memory _path, uint256 _amount, uint256 _minAmount)
internal virtual
returns (uint256, uint256) {
// If 0 is passed as sell amount, we get the whole contract balance
if (_amount == 0) {
_amount = _contractTokenBalance(_rewardToken);
}
if (_amount == 0) {
return (0, 0);
}
if (_path.length != 0) {
// Uni v3 swap
ISwapRouter _swapRouter = ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);
IERC20Detailed(_rewardToken).safeIncreaseAllowance(address(_swapRouter), _amount);
// multi hop swap params
ISwapRouter.ExactInputParams memory params = ISwapRouter.ExactInputParams({
path: _path,
recipient: address(this),
deadline: block.timestamp + 100,
amountIn: _amount,
amountOutMinimum: _minAmount
});
// do the swap and return the amount swapped and the amount received
return (_amount, _swapRouter.exactInput(params));
} else {
// Uni v2 swap
IUniswapV2Router02 _uniRouter = uniswapRouterV2;
// approve the uniswap router to spend our reward
IERC20Detailed(_rewardToken).safeIncreaseAllowance(address(_uniRouter), _amount);
// do the trade with all `_rewardToken` in this contract
address[] memory _pathUniv2 = new address[](3);
_pathUniv2[0] = _rewardToken;
_pathUniv2[1] = weth;
_pathUniv2[2] = token;
uint256[] memory _amounts = _uniRouter.swapExactTokensForTokens(
_amount,
_minAmount,
_pathUniv2,
address(this),
block.timestamp + 100
);
// return the amount swapped and the amount received
return (_amounts[0], _amounts[_amounts.length - 1]);
}
}
/// @notice method used to sell all sellable rewards for `_token` on uniswap
/// @param _strategy IIdleCDOStrategy stategy instance
/// @param _sellAmounts array with amounts of rewards to sell
/// @param _minAmount array with amounts of _token buy for each reward sold. (should have the same length as _sellAmounts)
/// @param _skipReward array of flags for skipping the market sell of specific rewards (should have the same length as _sellAmounts)
/// @return _soldAmounts array with amounts of rewards actually sold
/// @return _swappedAmounts array with amounts of _token actually bought
/// @return _totSold total rewards sold in `_token`
function _sellAllRewards(IIdleCDOStrategy _strategy, uint256[] memory _sellAmounts, uint256[] memory _minAmount, bool[] memory _skipReward, bytes memory _extraData)
internal
returns (uint256[] memory _soldAmounts, uint256[] memory _swappedAmounts, uint256 _totSold) {
// Fetch state variables once to save gas
// get all rewards addresses
address[] memory _rewards = _strategy.getRewardTokens();
address _rewardToken;
bytes[] memory _paths = new bytes[](_rewards.length);
if (_extraData.length > 0) {
_paths = abi.decode(_extraData, (bytes[]));
}
uint256 rewardsLen = _rewards.length;
// Initialize the return array, containing the amounts received after swapping reward tokens
_soldAmounts = new uint256[](rewardsLen);
_swappedAmounts = new uint256[](rewardsLen);
// loop through all reward tokens
for (uint256 i; i < rewardsLen; ++i) {
_rewardToken = _rewards[i];
// check if it should be sold or not
if (_skipReward[i]) { continue; }
// do not sell stkAAVE but only AAVE if present
if (_rewardToken == stkAave) {
_rewardToken = AAVE;
}
// Market sell _rewardToken in this contract for _token
(_soldAmounts[i], _swappedAmounts[i]) = _sellReward(_rewardToken, _paths[i], _sellAmounts[i], _minAmount[i]);
_totSold += _swappedAmounts[i];
}
}
/// @param _tranche tranche address
/// @return last saved tranche price, in underlyings
function _tranchePrice(address _tranche) internal view returns (uint256) {
if (IdleCDOTranche(_tranche).totalSupply() == 0) {
return oneToken;
}
return _tranche == AATranche ? priceAA : priceBB;
}
/// @notice returns the current apr for a tranche based on trancheAPRSplitRatio and the provided AA ratio
/// @dev the apr for a tranche can be higher than the strategy apr
/// @param _tranche tranche token address
/// @param _AATrancheSplitRatio AA split ratio used for calculations
/// @return apr for the specific tranche
function _getApr(address _tranche, uint256 _AATrancheSplitRatio) internal view returns (uint256) {
uint256 stratApr = IIdleCDOStrategy(strategy).getApr();
uint256 _trancheAPRSplitRatio = trancheAPRSplitRatio;
bool isAATranche = _tranche == AATranche;
if (_AATrancheSplitRatio == 0) {
// if there are no AA tranches, apr for AA is 0 (all apr to BB and it will be equal to stratApr)
return isAATranche ? 0 : stratApr;
}
return isAATranche ?
// AA apr is: stratApr * AAaprSplitRatio / AASplitRatio
stratApr * _trancheAPRSplitRatio / _AATrancheSplitRatio :
// BB apr is: stratApr * BBaprSplitRatio / BBSplitRatio -> where
// BBaprSplitRatio is: (FULL_ALLOC - _trancheAPRSplitRatio) and
// BBSplitRatio is: (FULL_ALLOC - _AATrancheSplitRatio)
stratApr * (FULL_ALLOC - _trancheAPRSplitRatio) / (FULL_ALLOC - _AATrancheSplitRatio);
}
/// @return _locked amount of harvested rewards that are still not available to be redeemed
function _lockedRewards() internal view returns (uint256 _locked) {
uint256 _releaseBlocksPeriod = releaseBlocksPeriod;
uint256 _blocksSinceLastHarvest = block.number - latestHarvestBlock;
uint256 _harvestedRewards = harvestedRewards;
// NOTE: _harvestedRewards is never set to 0, but rather to 1 to save some gas
if (_harvestedRewards > 1 && _blocksSinceLastHarvest < _releaseBlocksPeriod) {
// progressively release harvested rewards
_locked = _harvestedRewards * (_releaseBlocksPeriod - _blocksSinceLastHarvest) / _releaseBlocksPeriod;
}
}
// ###################
// Protected
// ###################
/// @notice This method is used to lend user funds in the lending provider through an IIdleCDOStrategy
/// The method:
/// - redeems rewards (if any) from the lending provider
/// - converts the rewards in underlyings through uniswap v2 or v3
/// - calls _updateAccounting to update the accounting of the system with the new underlyings received
/// - it then convert fees in tranche tokens
/// - finally it deposits the (initial unlent balance + the underlyings get from uniswap - fees) in the
/// lending provider through the IIdleCDOStrategy `deposit` call
/// The method will be called by an external, whitelisted, keeper bot which will call the method sistematically (eg once a day)
/// @dev can be called only by the rebalancer or the owner
/// @param _skipFlags array of flags, [0] = skip reward redemption, [1] = skip incentives update, [2] = skip fee deposit, [3] = skip all
/// @param _skipReward array of flags for skipping the market sell of specific rewards. Length should be equal to the `IIdleCDOStrategy(strategy).getRewardTokens()` array
/// @param _minAmount array of min amounts for uniswap trades. Lenght should be equal to the _skipReward array
/// @param _sellAmounts array of amounts (of reward tokens) to sell on uniswap. Lenght should be equal to the _minAmount array
/// if a sellAmount is 0 the whole contract balance for that token is swapped
/// @param _extraData bytes to be passed to the redeemRewards call
/// @return _res array of arrays with the following elements:
/// [0] _soldAmounts array with amounts of rewards actually sold
/// [1] _swappedAmounts array with amounts of _token actually bought
/// [2] _redeemedRewards array with amounts of rewards redeemed
function harvest(
// _skipFlags[0] _skipRedeem,
// _skipFlags[1] _skipIncentivesUpdate, [DEPRECATED]
// _skipFlags[2] _skipFeeDeposit,
// _skipFlags[3] _skipRedeem && _skipIncentivesUpdate && _skipFeeDeposit,
bool[] calldata _skipFlags,
bool[] calldata _skipReward,
uint256[] calldata _minAmount,
uint256[] calldata _sellAmounts,
bytes[] calldata _extraData
) public
virtual
returns (uint256[][] memory _res) {
_checkOnlyOwnerOrRebalancer();
// initalize the returned array (elements will be [_soldAmounts, _swappedAmounts, _redeemedRewards])
_res = new uint256[][](3);
// Fetch state variable once to save gas
IIdleCDOStrategy _strategy = IIdleCDOStrategy(strategy);
// Check whether to redeem rewards from strategy or not
if (!_skipFlags[3]) {
uint256 _totSold;
if (!_skipFlags[0]) {
// Redeem all rewards associated with the strategy
_res[2] = _strategy.redeemRewards(_extraData[0]);
// Sell rewards
(_res[0], _res[1], _totSold) = _sellAllRewards(_strategy, _sellAmounts, _minAmount, _skipReward, _extraData[1]);
}
// update last saved harvest block number
latestHarvestBlock = block.number;
// update harvested rewards value (avoid setting it to 0 to save some gas)
harvestedRewards = _totSold == 0 ? 1 : _totSold;
// split converted rewards if any and update tranche prices
// NOTE: harvested rewards won't be counted directly but released over time
_updateAccounting();
if (!_skipFlags[2]) {
// Get fees in the form of totalSupply diluition
_depositFees();
}
}
// Deposit the remaining balance in the lending provider and
// keep some unlent balance for cheap redeems and as reserve of last resort
uint256 underlyingBal = _contractTokenBalance(token);
uint256 idealUnlent = getContractValue() * unlentPerc / FULL_ALLOC;
if (underlyingBal > idealUnlent) {
// Put unlent balance at work in the lending provider
_strategy.deposit(underlyingBal - idealUnlent);
}
}
/// @notice method used to redeem underlyings from the lending provider
/// @dev can be called only by the rebalancer or the owner
/// @param _amount in underlyings to liquidate from lending provider
/// @param _revertIfNeeded flag to revert if amount liquidated is too low
/// @return liquidated amount in underlyings
function liquidate(uint256 _amount, bool _revertIfNeeded) external returns (uint256) {
_checkOnlyOwnerOrRebalancer();
return _liquidate(_amount, _revertIfNeeded);
}
// ###################
// onlyOwner
// ###################
/// @dev automatically reverts if strategyPrice decreased more than `_maxDecreaseDefault`
/// @param _maxDecreaseDefault max value, in % where `100000` = 100%, of accettable price decrease for the strategy
function setMaxDecreaseDefault(uint256 _maxDecreaseDefault) external {
_checkOnlyOwner();
require(_maxDecreaseDefault < FULL_ALLOC, '7');
maxDecreaseDefault = _maxDecreaseDefault;
}
/// @param _active flag to allow Adaptive Yield Split
function setIsAYSActive(bool _active) external {
_checkOnlyOwner();
isAYSActive = _active;
}
/// @param _allowed flag to allow AA withdraws
function setAllowAAWithdraw(bool _allowed) external {
_checkOnlyOwner();
allowAAWithdraw = _allowed;
}
/// @param _allowed flag to allow BB withdraws
function setAllowBBWithdraw(bool _allowed) external {
_checkOnlyOwner();
allowBBWithdraw = _allowed;
}
/// @param _allowed flag to enable the 'default' check (whether _strategyPrice decreased or not)
function setSkipDefaultCheck(bool _allowed) external {
_checkOnlyOwner();
skipDefaultCheck = _allowed;
}
/// @param _allowed flag to enable the check if redeemed amount during liquidations is enough
function setRevertIfTooLow(bool _allowed) external {
_checkOnlyOwner();
revertIfTooLow = _allowed;
}
/// @param _rebalancer new rebalancer address
function setRebalancer(address _rebalancer) external {
_checkOnlyOwner();
require((rebalancer = _rebalancer) != address(0), '0');
}
/// @param _feeReceiver new fee receiver address
function setFeeReceiver(address _feeReceiver) external {
_checkOnlyOwner();
require((feeReceiver = _feeReceiver) != address(0), '0');
}
/// @param _guardian new guardian (pauser) address
function setGuardian(address _guardian) external {
_checkOnlyOwner();
require((guardian = _guardian) != address(0), '0');
}
/// @param _diff max liquidation diff tolerance in underlyings
function setLiquidationTolerance(uint256 _diff) external {
_checkOnlyOwner();
liquidationTolerance = _diff;
}
/// @param _val stkIDLE per underlying required for deposits
function setStkIDLEPerUnderlying(uint256 _val) external {
_checkOnlyOwner();
stkIDLEPerUnderlying = _val;
}
/// @param _aprSplit min apr split for AA, considering FULL_ALLOC = 100%
function setMinAprSplitAYS(uint256 _aprSplit) external {
_checkOnlyOwner();
require((minAprSplitAYS = _aprSplit) <= FULL_ALLOC, '7');
minAprSplitAYS = _aprSplit;
}
/// @param _fee new fee
function setFee(uint256 _fee) external {
_checkOnlyOwner();
require((fee = _fee) <= MAX_FEE, '7');
}
/// @param _unlentPerc new unlent percentage
function setUnlentPerc(uint256 _unlentPerc) external {
_checkOnlyOwner();
require((unlentPerc = _unlentPerc) <= FULL_ALLOC, '7');
}
/// @notice set new release block period. WARN: this should be called only when there
/// are no active rewards being unlocked
/// @param _releaseBlocksPeriod new # of blocks after an harvest during which
/// harvested rewards gets progressively redistriburted to users
function setReleaseBlocksPeriod(uint256 _releaseBlocksPeriod) external {
_checkOnlyOwner();
releaseBlocksPeriod = _releaseBlocksPeriod;
}
/// @param _trancheAPRSplitRatio new apr split ratio
function setTrancheAPRSplitRatio(uint256 _trancheAPRSplitRatio) external {
_checkOnlyOwner();
require((trancheAPRSplitRatio = _trancheAPRSplitRatio) <= FULL_ALLOC, '7');
}
/// @param _diffBps tolerance in % (FULL_ALLOC = 100%) for socializing small losses
function setLossToleranceBps(uint256 _diffBps) external {
_checkOnlyOwner();
lossToleranceBps = _diffBps;
}
/// @dev toggle stkIDLE requirement for tranche
/// @param _tranche address
function toggleStkIDLEForTranche(address _tranche) external {
_checkOnlyOwner();
address aa = AATranche;
require(_tranche == BBTranche || _tranche == aa, '9');
if (_tranche == aa) {
AAStaking = AAStaking == address(0) ? address(1) : address(0);
return;
}
BBStaking = BBStaking == address(0) ? address(1) : address(0);
}
/// @notice this method updates the accounting of the contract and effectively splits the yield/loss between the
/// AA and BB tranches. This can be called at any time as is called automatically on each deposit/redeem. It's here
/// just to be called when a default happened, as deposits/redeems are paused, but we need to update
/// the loss for junior holders
function updateAccounting() external {
_checkOnlyOwnerOrGuardian();
skipDefaultCheck = true;
_updateAccounting();
// _updateAccounting can set `skipDefaultCheck` to true in case of default
// but this can be manually be reset to true if needed
skipDefaultCheck = false;
}
/// @notice pause deposits and redeems for all classes of tranches
/// @dev can be called by both the owner and the guardian
function emergencyShutdown() external {
_checkOnlyOwnerOrGuardian();
_emergencyShutdown(false);
}
function _emergencyShutdown(bool isAAWithdrawAllowed) internal {
// prevent deposits
_pause();
// prevent withdraws
allowAAWithdraw = isAAWithdrawAllowed;
allowBBWithdraw = false;
// Allow deposits/withdraws (once selectively re-enabled, eg for AA holders)
// without checking for lending protocol default
skipDefaultCheck = true;
revertIfTooLow = true;
}
/// @notice allow deposits and redeems for all classes of tranches
/// @dev can be called by the owner only
function restoreOperations() external {
_checkOnlyOwner();
// restore deposits
_unpause();
// restore withdraws
allowAAWithdraw = true;
allowBBWithdraw = true;
// Allow deposits/withdraws but checks for lending protocol default
skipDefaultCheck = false;
revertIfTooLow = true;
}
/// @notice Pauses deposits
/// @dev can be called by both the owner and the guardian
function pause() external {
_checkOnlyOwnerOrGuardian();
_pause();
}
/// @notice Unpauses deposits
/// @dev can be called by both the owner and the guardian
function unpause() external {
_checkOnlyOwnerOrGuardian();
_unpause();
}
// ###################
// Helpers
// ###################
/// @dev Check that the msg.sender is the either the owner or the guardian
function _checkOnlyOwnerOrGuardian() internal view {
require(msg.sender == guardian || msg.sender == owner(), "6");
}
/// @dev Check that the msg.sender is the either the owner or the rebalancer
function _checkOnlyOwnerOrRebalancer() internal view {
require(msg.sender == rebalancer || msg.sender == owner(), "6");
}
/// @notice returns the current balance of this contract for a specific token
/// @param _token token address
/// @return balance of `_token` for this contract
function _contractTokenBalance(address _token) internal view returns (uint256) {
return IERC20Detailed(_token).balanceOf(address(this));
}
/// @dev Set allowance for _token to unlimited for _spender
/// @param _token token address
/// @param _spender spender address
function _allowUnlimitedSpend(address _token, address _spender) internal {
IERC20Detailed(_token).safeIncreaseAllowance(_spender, type(uint256).max);
}
/// @dev Set last caller and block.number hash. This should be called at the beginning of the first function to protect
function _updateCallerBlock() internal {
_lastCallerBlock = keccak256(abi.encodePacked(tx.origin, block.number));
}
/// @dev Check that the second function is not called in the same tx from the same tx.origin
function _checkSameTx() internal view {
require(keccak256(abi.encodePacked(tx.origin, block.number)) != _lastCallerBlock, "8");
}
/// @notice concat 2 strings in a single one
/// @param a first string
/// @param b second string
/// @return new string with a and b concatenated
function _concat(string memory a, string memory b) internal pure returns (string memory) {
return string(abi.encodePacked(a, b));
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.10;
import '@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol';
contract IdleCDOStorage {
// constant to represent 100%
uint256 public constant FULL_ALLOC = 100000;
// max fee, relative to FULL_ALLOC
uint256 public constant MAX_FEE = 20000;
// one token
uint256 public constant ONE_TRANCHE_TOKEN = 10**18;
// variable used to save the last tx.origin and block.number
bytes32 internal _lastCallerBlock;
// variable used to save the block of the latest harvest
uint256 internal latestHarvestBlock;
// WETH address
address public weth;
// [DEPRECATED] tokens used to incentivize the idle tranche ideal ratio
address[] public incentiveTokens;
// underlying token (eg DAI)
address public token;
// address that can only pause/unpause the contract in case of emergency
address public guardian;
// one `token` (eg for DAI 10**18)
uint256 public oneToken;
// address that can call the 'harvest' method and lend pool assets
address public rebalancer;
// address of the uniswap v2 router
IUniswapV2Router02 internal uniswapRouterV2;
// Flag for allowing AA withdraws
bool public allowAAWithdraw;
// Flag for allowing BB withdraws
bool public allowBBWithdraw;
// Flag for allowing to enable reverting in case the strategy gives back less
// amount than the requested one
bool public revertIfTooLow;
// Flag to enable the `Default Check` (related to the emergency shutdown)
bool public skipDefaultCheck;
// address of the strategy used to lend funds
address public strategy;
// address of the strategy token which represent the position in the lending provider
address public strategyToken;
// address of AA Tranche token contract
address public AATranche;
// address of BB Tranche token contract
address public BBTranche;
// address for stkIDLE gating for AA tranche. addr(0) -> inactive, addr(1) -> active
address public AAStaking;
// address for stkIDLE gating for BB tranche. addr(0) -> inactive, addr(1) -> active
address public BBStaking;
// Apr split ratio for AA tranches
// (relative to FULL_ALLOC so 50% => 50000 => 50% of the interest to tranche AA)
uint256 public trancheAPRSplitRatio; //
// [DEPRECATED] Ideal tranche split ratio in `token` value
// (relative to FULL_ALLOC so 50% => 50000 means 50% of tranches (in value) should be AA)
uint256 public trancheIdealWeightRatio;
// Price for minting AA tranche, in underlyings
uint256 public priceAA;
// Price for minting BB tranche, in underlyings
uint256 public priceBB;
// last saved net asset value (in `token`) for AA tranches
uint256 public lastNAVAA;
// last saved net asset value (in `token`) for BB tranches
uint256 public lastNAVBB;
// last saved lending provider price
uint256 public lastStrategyPrice;
// Keeps track of unclaimed fees for feeReceiver
uint256 public unclaimedFees;
// Keeps an unlent balance both for cheap redeem and as 'insurance of last resort'
uint256 public unlentPerc;
// Fee amount (relative to FULL_ALLOC)
uint256 public fee;
// address of the fee receiver
address public feeReceiver;
// [DEPRECATED] trancheIdealWeightRatio ± idealRanges, used in updateIncentives
uint256 public idealRange;
// period, in blocks, for progressively releasing harvested rewards to users
uint256 public releaseBlocksPeriod;
// amount of rewards sold in the last harvest (in `token`)
uint256 internal harvestedRewards;
// stkAave address
address internal constant stkAave = address(0x4da27a545c0c5B758a6BA100e3a049001de870f5);
// aave address
address internal constant AAVE = address(0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9);
// [DEPRECATED] if the cdo receive stkAAVE
bool internal isStkAAVEActive;
// referral address of the strategy developer
address public referral;
// amount of fee for feeReceiver. Max is FULL_ALLOC
uint256 public feeSplit;
// if Adaptive Yield Split is active
bool public isAYSActive;
// constant to represent 99% (for ADS AA ratio upper limit)
uint256 internal constant AA_RATIO_LIM_UP = 99000;
// constant to represent 50% (for ADS AA ratio lower limit)
uint256 internal constant AA_RATIO_LIM_DOWN = 50000;
address internal constant STK_IDLE = address(0xaAC13a116eA7016689993193FcE4BadC8038136f);
// Referral event
event Referral(uint256 _amount, address _ref);
// tolerance in underlyings when redeeming
uint256 public liquidationTolerance;
// Add new variables here. For each storage slot
// used, reduce the __gap length by 1.
// #######################
// Min apr ratio for AA tranches when using AYS
uint256 public minAprSplitAYS;
// Max strategy price decrease before triggering a default
uint256 public maxDecreaseDefault;
// The tolerance for the loss socialized so equally distributed between junior and senior tranches.
uint256 public lossToleranceBps;
// Amount of stkIDLE required to mint 1 underlying
uint256 public stkIDLEPerUnderlying;
// uint256 public test;
// #######################
// This is empty reserved space in storage that is put
// in place in Upgradeable contracts. It allows us to
// freely add new state variables in the future without
// compromising the storage compatibility with existing
// deployments.
// The size of the __gap array is calculated so that the
// amount of storage used by a contract always adds up to
// always the same number, 50 in this case.
uint256[46] private __gap;
// uint256[45] private __gap; -> after adding `test`
// #######################
// IMPORTANT: Do not add any variables below `__gap`
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
/// @dev ERC20 representing a tranche token
contract IdleCDOTranche is ERC20 {
// allowed minter address
address public minter;
/// @param _name tranche name
/// @param _symbol tranche symbol
constructor(
string memory _name, // eg. IdleDAI
string memory _symbol // eg. IDLEDAI
) ERC20(_name, _symbol) {
// minter is msg.sender which is IdleCDO (in initialize)
minter = msg.sender;
}
/// @param account that should receive the tranche tokens
/// @param amount of tranche tokens to mint
function mint(address account, uint256 amount) external {
require(msg.sender == minter, 'TRANCHE:!AUTH');
_mint(account, amount);
}
/// @param account that should have the tranche tokens burned
/// @param amount of tranche tokens to burn
function burn(address account, uint256 amount) external {
require(msg.sender == minter, 'TRANCHE:!AUTH');
_burn(account, amount);
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.10;
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
interface IERC20Detailed is IERC20Upgradeable {
function name() external view returns(string memory);
function symbol() external view returns(string memory);
function decimals() external view returns(uint256);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.10;
interface IIdleCDOStrategy {
function strategyToken() external view returns(address);
function token() external view returns(address);
function tokenDecimals() external view returns(uint256);
function oneToken() external view returns(uint256);
function redeemRewards(bytes calldata _extraData) external returns(uint256[] memory);
function pullStkAAVE() external returns(uint256);
function price() external view returns(uint256);
function getRewardTokens() external view returns(address[] memory);
function deposit(uint256 _amount) external returns(uint256);
// _amount in `strategyToken`
function redeem(uint256 _amount) external returns(uint256);
// _amount in `token`
function redeemUnderlying(uint256 _amount) external returns(uint256);
function getApr() external view returns(uint256);
}{
"optimizer": {
"enabled": true,
"runs": 170
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"_ref","type":"address"}],"name":"Referral","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"AAStaking","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"AATranche","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BBStaking","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BBTranche","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FULL_ALLOC","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE_TRANCHE_TOKEN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"_setLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"allowAAWithdraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allowBBWithdraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositAA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_referral","type":"address"}],"name":"depositAARef","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositBB","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_referral","type":"address"}],"name":"depositBBRef","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emergencyShutdown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeSplit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tranche","type":"address"}],"name":"getApr","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentAARatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getIncentiveTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governanceRecoveryFund","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool[]","name":"_skipFlags","type":"bool[]"},{"internalType":"bool[]","name":"_skipReward","type":"bool[]"},{"internalType":"uint256[]","name":"_minAmount","type":"uint256[]"},{"internalType":"uint256[]","name":"_sellAmounts","type":"uint256[]"},{"internalType":"bytes[]","name":"_extraData","type":"bytes[]"}],"name":"harvest","outputs":[{"internalType":"uint256[][]","name":"_res","type":"uint256[][]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"idealRange","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"incentiveTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_limit","type":"uint256"},{"internalType":"address","name":"_guardedToken","type":"address"},{"internalType":"address","name":"_governanceFund","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_rebalancer","type":"address"},{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"uint256","name":"_trancheAPRSplitRatio","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address[]","name":"","type":"address[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isAYSActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastNAVAA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastNAVBB","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastStrategyPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"limit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"_revertIfNeeded","type":"bool"}],"name":"liquidate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"liquidationTolerance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lossToleranceBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxDecreaseDefault","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minAprSplitAYS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oneToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceAA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceBB","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebalancer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referral","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"releaseBlocksPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"restoreOperations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revertIfTooLow","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_allowed","type":"bool"}],"name":"setAllowAAWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_allowed","type":"bool"}],"name":"setAllowBBWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeReceiver","type":"address"}],"name":"setFeeReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guardian","type":"address"}],"name":"setGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_active","type":"bool"}],"name":"setIsAYSActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_diff","type":"uint256"}],"name":"setLiquidationTolerance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_diffBps","type":"uint256"}],"name":"setLossToleranceBps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxDecreaseDefault","type":"uint256"}],"name":"setMaxDecreaseDefault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_aprSplit","type":"uint256"}],"name":"setMinAprSplitAYS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rebalancer","type":"address"}],"name":"setRebalancer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_releaseBlocksPeriod","type":"uint256"}],"name":"setReleaseBlocksPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_allowed","type":"bool"}],"name":"setRevertIfTooLow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_allowed","type":"bool"}],"name":"setSkipDefaultCheck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_val","type":"uint256"}],"name":"setStkIDLEPerUnderlying","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_trancheAPRSplitRatio","type":"uint256"}],"name":"setTrancheAPRSplitRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_unlentPerc","type":"uint256"}],"name":"setUnlentPerc","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"skipDefaultCheck","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stkIDLEPerUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strategy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strategyToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tranche","type":"address"}],"name":"toggleStkIDLEForTranche","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trancheAPRSplitRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trancheIdealWeightRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tranche","type":"address"}],"name":"tranchePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transferToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unclaimedFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unlentPerc","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateAccounting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tranche","type":"address"}],"name":"virtualPrice","outputs":[{"internalType":"uint256","name":"_virtualPrice","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawAA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawBB","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b5060cf80546001600160a01b0319166001179055615bc2806100336000396000f3fe60806040523480156200001157600080fd5b5060043610620005295760003560e01c80636f47d99b11620002ad578063a8c62e761162000179578063e3e3936811620000df578063efdcd974116200009e578063efdcd9741462000afc578063f2fde38b1462000b13578063f8623d9b1462000b2a578063fc0c546a1462000b41578063fdf4c0dc1462000b55578063fe81a0241462000b5f57600080fd5b8063e3e393681462000a9c578063e70875ad1462000ab0578063e86d8c341462000ac7578063eb120bf41462000ade578063edd636fb1462000af257600080fd5b8063cc1158051162000138578063cc1158051462000a38578063d816f5dc1462000a4f578063dc82697c1462000a66578063ddca3f431462000a70578063dfd5b1c91462000a7a578063e07eace61462000a8557600080fd5b8063a8c62e7614620009df578063b3f0067414620009f3578063b450dfce1462000a07578063bc063e1a1462000a1e578063c9aba3561462000a2857600080fd5b80638f5aa090116200021f5780639af6485411620001de5780639af6485414620009715780639d3ef4b21462000988578063a219d218146200099d578063a27eccc114620009b4578063a3d0bd4814620009be578063a4d66daf14620009d557600080fd5b80638f5aa090146200090b5780639290d427146200092257806392b29be3146200093957806394929dc1146200094357806399abe5e8146200095a57600080fd5b806383975b67116200026c57806383975b6714620008b75780638456cb5914620008c157806387109ffd14620008cb5780638a0dac4a14620008e25780638da5cb5b14620008f957600080fd5b80636f47d99b1462000870578063715018a61462000885578063734d8287146200088f578063747efea114620008995780637509539214620008ad57600080fd5b80632c2a7ca411620003f957806344966ba0116200035f5780635c975abb116200031e5780635c975abb146200081857806362adade514620008245780636373ea69146200082e57806366a4c633146200083857806369fe0e2d14620008425780636cfd1553146200085957600080fd5b806344966ba014620007ba578063452a932014620007ce5780634684059014620007e2578063494347e714620007f957806355c70701146200080357600080fd5b80633f4ba83a11620003b85780633f4ba83a146200075a5780633fc8cef31462000764578063400f7d321462000778578063408f3a30146200078257806340bd61091462000799578063435d44d914620007a357600080fd5b80632c2a7ca414620007025780632cc0800e146200070c5780633403c2fc1462000723578063387af1bd146200072d5780633b28d537146200074157600080fd5b806318dc7195116200049f5780632047782a116200045e5780632047782a146200069f57806325cdd86014620006a957806325f66adf14620006b35780632758db0c14620006bd57806329811ee514620006d45780632a3e4dc214620006eb57600080fd5b806318dc719514620006265780631a7e0ce5146200063d5780631cac6454146200065c5780631cf7a8ff14620006735780631ed4fd97146200068a57600080fd5b80631072cbea11620004ec5780631072cbea14620005c157806312361ac214620005d85780631441a5a914620005e25780631533c31e14620005fb57806315c44b8b146200061257600080fd5b806301d22ccd146200052e57806303311d75146200055f57806306a9a8bf1462000585578063085a2b78146200059e578063088f4b7814620005a8575b600080fd5b60d25462000542906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b620005766200057036600462004015565b62000b69565b60405162000556919062004115565b6200058f60ed5481565b60405190815260200162000556565b6200058f60da5481565b620005bf620005b9366004620041b2565b62000f88565b005b620005bf620005d2366004620041e8565b62000fa5565b6200058f60dc5481565b60e854620005429061010090046001600160a01b031681565b620005bf6200060c36600462004217565b62000fcf565b60d95462000542906001600160a01b031681565b620005bf62000637366004620042a0565b62000fde565b60ea546200064b9060ff1681565b604051901515815260200162000556565b620005bf6200066d36600462004217565b62001602565b620005bf6200068436600462004217565b62001611565b60d3546200064b90600160b81b900460ff1681565b6200058f60e55481565b6200058f62001649565b6200058f60db5481565b6200058f620006ce366004620043d1565b6200165c565b6200058f620006e536600462004404565b6200167d565b62000542620006fc36600462004217565b62001696565b6200058f60ec5481565b6200058f6200071d36600462004424565b620016c1565b620005bf620016de565b60ca5462000542906001600160a01b031681565b6200074b620016f6565b60405162000556919062004492565b620005bf6200175a565b60cd5462000542906001600160a01b031681565b6200058f60dd5481565b620005bf6200079336600462004217565b6200176e565b6200058f60ee5481565b620005bf620007b436600462004217565b6200177d565b60d65462000542906001600160a01b031681565b60d05462000542906001600160a01b031681565b620005bf620007f3366004620041b2565b620017b7565b620005bf620017df565b60d3546200064b90600160a01b900460ff1681565b60335460ff166200064b565b6200058f60de5481565b6200058f60e95481565b6200058f60ef5481565b620005bf6200085336600462004217565b62001815565b620005bf6200086a36600462004404565b62001849565b60d3546200064b90600160b01b900460ff1681565b620005bf62001890565b6200058f60e15481565b60d55462000542906001600160a01b031681565b6200058f60eb5481565b620005bf620018a6565b620005bf620018d4565b620005bf620008dc36600462004217565b620018e8565b620005bf620008f336600462004404565b6200191c565b6065546001600160a01b031662000542565b620005bf6200091c366004620041b2565b62001963565b6200058f6200093336600462004404565b6200198b565b6200058f60e25481565b620005bf6200095436600462004217565b620019e1565b6200058f6200096b36600462004217565b620019f0565b6200058f6200098236600462004217565b62001a60565b60d3546200064b90600160a81b900460ff1681565b6200058f620009ae36600462004404565b62001ad0565b6200058f60d15481565b620005bf620009cf36600462004217565b62001add565b6200058f60c95481565b60d45462000542906001600160a01b031681565b60e45462000542906001600160a01b031681565b6200058f62000a1836600462004217565b62001b12565b6200058f614e2081565b6200058f670de0b6b3a764000081565b620005bf62000a49366004620041b2565b62001b2f565b6200058f62000a6036600462004424565b62001b57565b6200058f62001b74565b6200058f60e35481565b6200058f620186a081565b620005bf62000a96366004620041b2565b62001c74565b60d75462000542906001600160a01b031681565b6200058f62000ac136600462004217565b62001c9c565b620005bf62000ad836600462004217565b62001cb9565b60d85462000542906001600160a01b031681565b6200058f60e65481565b620005bf62000b0d36600462004404565b62001cc8565b620005bf62000b2436600462004404565b62001d0f565b620005bf62000b3b36600462004404565b62001d8b565b60cf5462000542906001600160a01b031681565b6200058f60e05481565b6200058f60df5481565b606062000b7562001e99565b6040805160038082526080820190925290816020015b606081526020019060019003908162000b8b57505060d4549091506001600160a01b03168b8b600381811062000bc55762000bc5620044a7565b905060200201602081019062000bdc9190620041b2565b62000ea35760008c8c600081811062000bf95762000bf9620044a7565b905060200201602081019062000c109190620041b2565b62000e4357816001600160a01b0316638ec71e0c8686600081811062000c3a5762000c3a620044a7565b905060200281019062000c4e9190620044bd565b6040518363ffffffff1660e01b815260040162000c6d92919062004506565b6000604051808303816000875af115801562000c8d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000cb7919081019062004535565b8360028151811062000ccd5762000ccd620044a7565b602002602001018190525062000dfc82888880806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508b8b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508e8e808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c92508b91506001905081811062000dad5762000dad620044a7565b905060200281019062000dc19190620044bd565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062001f0292505050565b8560008151811062000e125762000e12620044a7565b602002602001018660018151811062000e2f5762000e2f620044a7565b602002602001018295508390528390525050505b4360cc55801562000e55578062000e58565b60015b60e75562000e6562002204565b8c8c600281811062000e7b5762000e7b620044a7565b905060200201602081019062000e929190620041b2565b62000ea15762000ea16200236c565b505b60cf5460009062000ebd906001600160a01b0316620023b2565b90506000620186a060e25462000ed262001b74565b62000ede9190620045d9565b62000eea919062004611565b90508082111562000f77576001600160a01b03831663b6b55f2562000f10838562004628565b6040518263ffffffff1660e01b815260040162000f2f91815260200190565b6020604051808303816000875af115801562000f4f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000f75919062004642565b505b5050509a9950505050505050505050565b62000f9262002420565b60ea805460ff1916911515919091179055565b62000faf62002420565b60ca5462000fcb906001600160a01b0384811691168362002470565b5050565b62000fd962002420565b60ee55565b600054610100900460ff161580801562000fff5750600054600160ff909116105b806200101b5750303b1580156200101b575060005460ff166001145b620010845760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015620010a8576000805461ff0019166101001790555b60cf546001600160a01b031615620010e75760405162461bcd60e51b81526020600482015260016024820152603160f81b60448201526064016200107b565b6001600160a01b038616620011105760405162461bcd60e51b81526004016200107b906200465c565b6001600160a01b038516620011395760405162461bcd60e51b81526004016200107b906200465c565b6001600160a01b038916620011625760405162461bcd60e51b81526004016200107b906200465c565b620186a0841115620011885760405162461bcd60e51b81526004016200107b9062004677565b62001192620024da565b6200119f8a89896200250e565b6000856001600160a01b031663747efea16040518163ffffffff1660e01b8152600401602060405180830381865afa158015620011e0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001206919062004692565b90506000816001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001249573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262001273919081019062004737565b9050620012ae60405180604001604052806015815260200174024b23632a1a2279020a0902a3930b731b43290169605d1b815250826200259f565b620012d56040518060400160405280600381526020016241415f60e81b815250836200259f565b604051620012e39062003faf565b620012f0929190620047b2565b604051809103906000f0801580156200130d573d6000803e3d6000fd5b5060d680546001600160a01b0319166001600160a01b0392909216919091179055604080518082019091526015815274024b23632a1a227902121102a3930b731b43290169605d1b60208201526200136690826200259f565b6200138d6040518060400160405280600381526020016242425f60e81b815250836200259f565b6040516200139b9062003faf565b620013a8929190620047b2565b604051809103906000f080158015620013c5573d6000803e3d6000fd5b5060d780546001600160a01b03199081166001600160a01b039384161790915560cf805482168e841690811790915560d4805483168b851617905560d58054831686851617905560d28054909216928b1692909217905560da8790556040805163313ce56760e01b815290516000929163313ce5679160048083019260209291908290030181865afa15801562001460573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001486919062004642565b6200149390600a620048d8565b60d181905560d3805460cd80546001600160a01b03191673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc217905560dc83905560dd8390556107d060e25561190060e655760101017a250d5630b4cf539739df2c5dacb4c659f2488d6001600160b81b031990911617905590506200150d8c89620025cd565b620015198389620025cd565b62001523620025e5565b60e055613a9860e35560e480546001600160a01b031990811673fb3bd022d5dacf95ee28a6b07825d4ff9c5b38141790915560d080546001600160a01b038d16921691909117905560ea805460ff1916600117905561c35060ec5561138860ed55620015ac60d45460d580546001600160a01b0319166001600160a01b03909216919091179055565b5050508015620015f6576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b6200160c62002420565b60ef55565b6200161b62002420565b620186a08160e28190551115620016465760405162461bcd60e51b81526004016200107b9062004677565b50565b600062001657600062002656565b905090565b60006200166862001e99565b620016748383620026f5565b90505b92915050565b6000620016778262001690600062002656565b620027d1565b60ce8181548110620016a757600080fd5b6000918252602090912001546001600160a01b0316905081565b60d754600090620016749084906001600160a01b031684620028ec565b620016e862002a38565b620016f4600062002a5f565b565b606060ce8054806020026020016040519081016040528092919081815260200182805480156200175057602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831162001731575b5050505050905090565b6200176462002a38565b620016f462002aa9565b6200177862002420565b60c955565b6200178762002420565b620186a08160ec8190551115620017b25760405162461bcd60e51b81526004016200107b9062004677565b60ec55565b620017c162002420565b60d38054911515600160b81b0260ff60b81b19909216919091179055565b620017e962002a38565b60d3805460ff60b81b1916600160b81b1790556200180662002204565b60d3805460ff60b81b19169055565b6200181f62002420565b614e208160e38190551115620016465760405162461bcd60e51b81526004016200107b9062004677565b6200185362002420565b60d280546001600160a01b0319166001600160a01b038316908117909155620016465760405162461bcd60e51b81526004016200107b906200465c565b6200189a62002afd565b620016f4600062002b59565b620018b062002420565b620018ba62002aa9565b60d3805463ffffffff60a01b19166201010160a01b179055565b620018de62002a38565b620016f462002bab565b620018f262002420565b620186a08110620019175760405162461bcd60e51b81526004016200107b9062004677565b60ed55565b6200192662002420565b60d080546001600160a01b0319166001600160a01b038316908117909155620016465760405162461bcd60e51b81526004016200107b906200465c565b6200196d62002420565b60d38054911515600160a81b0260ff60a81b19909216919091179055565b60de5460df5460009190620019d884620019a462001b74565b620019b08486620048e6565b60d6546001600160a01b03898116911614620019cd5784620019cf565b855b60da5462002beb565b50949350505050565b620019eb62002420565b60e655565b6000620019ff60335460ff1690565b158062001a15575060d354600160a81b900460ff165b62001a475760405162461bcd60e51b81526020600482015260016024820152603360f81b60448201526064016200107b565b60d754620016779083906001600160a01b031662002f11565b600062001a6f60335460ff1690565b158062001a85575060d354600160a01b900460ff165b62001ab75760405162461bcd60e51b81526020600482015260016024820152603360f81b60448201526064016200107b565b60d654620016779083906001600160a01b031662002f11565b600062001677826200313e565b62001ae762002420565b620186a08160da8190551115620016465760405162461bcd60e51b81526004016200107b9062004677565b60d654600090620016779083906001600160a01b031683620028ec565b62001b3962002420565b60d38054911515600160a01b0260ff60a01b19909216919091179055565b60d654600090620016749084906001600160a01b031684620028ec565b60d5546040805163313ce56760e01b815290516000926001600160a01b0316918391839163313ce5679160048083019260209291908290030181865afa15801562001bc3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001be9919062004642565b905060e15462001bf8620031d9565b60cf5462001c0f906001600160a01b0316620023b2565b62001c1c84600a620048d8565b62001c26620025e5565b62001c3187620023b2565b62001c3d9190620045d9565b62001c49919062004611565b62001c559190620048e6565b62001c61919062004628565b62001c6d919062004628565b9250505090565b62001c7e62002420565b60d38054911515600160b01b0260ff60b01b19909216919091179055565b60d754600090620016779083906001600160a01b031683620028ec565b62001cc362002420565b60eb55565b62001cd262002420565b60e480546001600160a01b0319166001600160a01b038316908117909155620016465760405162461bcd60e51b81526004016200107b906200465c565b62001d1962002afd565b6001600160a01b03811662001d805760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016200107b565b620016468162002b59565b62001d9562002420565b60d65460d7546001600160a01b03918216918381169116148062001dca5750806001600160a01b0316826001600160a01b0316145b62001dfc5760405162461bcd60e51b81526020600482015260016024820152603960f81b60448201526064016200107b565b806001600160a01b0316826001600160a01b0316141562001e585760d8546001600160a01b03161562001e3157600062001e34565b60015b60d880546001600160a01b0319166001600160a01b03929092169190911790555050565b60d9546001600160a01b03161562001e7257600062001e75565b60015b60d980546001600160a01b0319166001600160a01b03929092169190911790555050565b60d2546001600160a01b031633148062001ed057506065546001600160a01b03165b6001600160a01b0316336001600160a01b0316145b620016f45760405162461bcd60e51b81526020600482015260016024820152601b60f91b60448201526064016200107b565b606080600080886001600160a01b031663c4f59f9b6040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001f47573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262001f71919081019062004901565b905060008082516001600160401b0381111562001f925762001f9262004231565b60405190808252806020026020018201604052801562001fc757816020015b606081526020019060019003908162001fb15790505b5087519091501562001fec578680602001905181019062001fe991906200499a565b90505b8251806001600160401b0381111562002009576200200962004231565b60405190808252806020026020018201604052801562002033578160200160208202803683370190505b509650806001600160401b0381111562002051576200205162004231565b6040519080825280602002602001820160405280156200207b578160200160208202803683370190505b50955060005b81811015620021f4578481815181106200209f576200209f620044a7565b60200260200101519350898181518110620020be57620020be620044a7565b602002602001015115620020d257620021e1565b6001600160a01b038416734da27a545c0c5b758a6ba100e3a049001de870f514156200211057737fc66500c84a76ad7e9c93437bfc5ac33e2ddae993505b62002172848483815181106200212a576200212a620044a7565b60200260200101518e8481518110620021475762002147620044a7565b60200260200101518e8581518110620021645762002164620044a7565b60200260200101516200323b565b898381518110620021875762002187620044a7565b60200260200101898481518110620021a357620021a3620044a7565b6020026020010182815250828152505050868181518110620021c957620021c9620044a7565b602002602001015186620021de9190620048e6565b95505b620021ec8162004a6c565b905062002081565b5050505050955095509592505050565b60de5460df546000620022188284620048e6565b905060006200222662001b74565b60da54909150828211156200227a5760e354620186a09062002249858562004628565b620022559190620045d9565b62002261919062004611565b60e16000828254620022749190620048e6565b90915550505b60d65460009081906200229a906001600160a01b031685878a8762002beb565b60d75491935091506000908190620022bf906001600160a01b031687898b8962002beb565b9092509050620022d0838a62004a8a565b60de55600081128015620022ee575087620022eb8262004ad1565b12155b156200234a5760d354600160b81b900460ff16620023335760405162461bcd60e51b81526020600482015260016024820152600d60fa1b60448201526064016200107b565b600060df5562002344600162002a5f565b6200235a565b62002356818962004a8a565b60df555b5060dc929092555060dd555050505050565b60e1548015620016465760e45460d654620023969183916001600160a01b03918216911662003508565b50600060e15562001646620023ac600162002656565b620035f6565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015620023fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001677919062004642565b33620024346065546001600160a01b031690565b6001600160a01b031614620016f45760405162461bcd60e51b81526020600482015260016024820152601b60f91b60448201526064016200107b565b6040516001600160a01b038316602482015260448101829052620024d590849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526200366a565b505050565b600054610100900460ff16620025045760405162461bcd60e51b81526004016200107b9062004af1565b620016f462003746565b6001600160a01b038216620025375760405162461bcd60e51b81526004016200107b906200465c565b6001600160a01b038116620025605760405162461bcd60e51b81526004016200107b906200465c565b6200256a6200377c565b62002574620037b0565b60c983905560ca80546001600160a01b0319166001600160a01b038416179055620024d58162001d0f565b60608282604051602001620025b692919062004b3c565b604051602081830303815290604052905092915050565b62000fcb6001600160a01b03831682600019620037e4565b60d4546040805163501ad8ff60e11b815290516000926001600160a01b03169163a035b1fe9160048083019260209291908290030181865afa15801562002630573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001657919062004642565b600062003fbd826200266c576200389e62002671565b620039315b60d65490915060009062002691906001600160a01b031663ffffffff8416565b60d754909150600090620026b1906001600160a01b031663ffffffff8516565b620026bd9083620048e6565b905080620026d057506000949350505050565b80620026e0620186a084620045d9565b620026ec919062004611565b95945050505050565b60d45460405163852a12e360e01b8152600481018490526000916001600160a01b03169063852a12e3906024016020604051808303816000875af115801562002742573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002768919062004642565b90508115620027c15760eb54806200277e575060645b836200278b8284620048e6565b1015620027bf5760405162461bcd60e51b81526020600482015260016024820152603560f81b60448201526064016200107b565b505b8281111562001677575090919050565b60008060d460009054906101000a90046001600160a01b03166001600160a01b031663845bc8046040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002828573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200284e919062004642565b60da5460d654919250906001600160a01b03868116911614846200288757806200287957826200287c565b60005b935050505062001677565b80620028c9576200289c85620186a062004628565b620028ab83620186a062004628565b620028b79085620045d9565b620028c3919062004611565b620028e2565b84620028d68385620045d9565b620028e2919062004611565b9695505050505050565b6000620028f862003947565b83620029045762002a31565b6200290f846200398f565b620029546040516bffffffffffffffffffffffff193260601b16602082015243603482015260540160408051601f19818403018152919052805160209091012060cb55565b6200295e620039e8565b6200296862002204565b62002974838562003a75565b60cf546001600160a01b031660006200298d82620023b2565b9050620029a66001600160a01b03831633308962003c57565b620029ca81620029b684620023b2565b620029c2919062004628565b338762003508565b9250620029dc620023ac600162002656565b6001600160a01b0384161562002a2e57604080518781526001600160a01b03861660208201527f496d589d8b7eb829a8d7b30e24a326ac33991f5cea96429b69231a6b15b54b1d910160405180910390a15b50505b9392505050565b60d0546001600160a01b031633148062001ed057506065546001600160a01b031662001ebb565b62002a6962002bab565b60d3805460ff60b01b1962ff00ff60a81b19931515600160a01b029390931663ff00ffff60a01b1990911617600160b81b1791909116600160b01b179055565b62002ab362003c91565b6033805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6065546001600160a01b03163314620016f45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016200107b565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b62002bb562003947565b6033805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25862002ae03390565b6000806000876001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002c2f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002c55919062004642565b905085158062002c63575080155b1562002c7857505060d1549050600062002f07565b600062002c86878962004b6f565b90508062002ca75762002c99896200313e565b600093509350505062002f07565b600081131562002ce057620186a060e3548262002cc5919062004bb4565b62002cd1919062004c45565b62002cdd908262004b6f565b90505b60d65460d7546001600160a01b0391821691908116908b1682148062002d07578262002d09565b815b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002d47573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002d6d919062004642565b62002d7b5783955062002ed1565b600084131562002dd3576000620186a062002d978a8262004628565b62002da3908762004bb4565b62002daf919062004c45565b90508162002dbe578062002dca565b62002dca818662004b6f565b96505062002ed1565b620186a08a60ee5462002de79190620045d9565b62002df3919062004611565b62002dfe8562004ad1565b1162002e575760df5460de5460009062002e1a908390620048e6565b62002e26838862004bb4565b62002e32919062004c45565b90508262002e41578062002e4d565b62002e4d818762004b6f565b9750505062002ed1565b60008162002e66578962002e72565b62002e728a8c62004628565b9050600062002e82868362004a8a565b9050600081131562002ea6578262002e9b578562002e9e565b60005b975062002ece565b8262002eca57600062002eb98362004ad1565b985098505050505050505062002f07565b8097505b50505b84670de0b6b3a764000062002ee7888c62004a8a565b62002ef39190620045d9565b62002eff919062004611565b965050505050505b9550959350505050565b600062002f1d62003cdc565b62002f2762003d38565b62002f31620039e8565b62002f3b62002204565b8262002faf576040516370a0823160e01b81523360048201526001600160a01b038316906370a0823190602401602060405180830381865afa15801562002f86573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002fac919062004642565b92505b8262002fcf5760405162461bcd60e51b81526004016200107b906200465c565b60cf546001600160a01b0316600062002fe882620023b2565b9050670de0b6b3a764000062002ffe856200313e565b6200300a9087620045d9565b62003016919062004611565b925082818111156200305557816200304662003033828762004628565b60d354600160b01b900460ff16620026f5565b620030529190620048e6565b93505b604051632770a7eb60e21b8152336004820152602481018790526001600160a01b03861690639dc29fac90604401600060405180830381600087803b1580156200309e57600080fd5b505af1158015620030b3573d6000803e3d6000fd5b505060d6546001600160a01b03888116911614159150620030f09050578060de6000828254620030e4919062004628565b909155506200310a9050565b8060df600082825462003104919062004628565b90915550505b6200311a620023ac600162002656565b620031306001600160a01b038416338662002470565b505050620016776001609755565b6000816001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200317f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620031a5919062004642565b620031b257505060d15490565b60d6546001600160a01b03838116911614620031d15760dd5462001677565b505060dc5490565b60e65460cc54600091908290620031f1904362004628565b60e7549091506001811180156200320757508282105b156200323557826200321a838262004628565b620032269083620045d9565b62003232919062004611565b93505b50505090565b6000808362003252576200324f86620023b2565b93505b836200326457506000905080620034ff565b8451156200334e5773e592427a0aece92de3edee1f18e0157c05861564620032976001600160a01b0388168287620037e4565b6040805160a0810182528781523060208201526000918101620032bc426064620048e6565b815260200187815260200186815250905085826001600160a01b031663c04b8d59836040518263ffffffff1660e01b8152600401620032fc919062004c79565b6020604051808303816000875af11580156200331c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003342919062004642565b935093505050620034ff565b60d3546001600160a01b03908116906200336c9088168287620037e4565b60408051600380825260808201909252600091602082016060803683370190505090508781600081518110620033a657620033a6620044a7565b6001600160a01b03928316602091820292909201015260cd54825191169082906001908110620033da57620033da620044a7565b6001600160a01b03928316602091820292909201015260cf548251911690829060029081106200340e576200340e620044a7565b6001600160a01b03928316602091820292909201015260009083166338ed1739888885306200343f426064620048e6565b6040518663ffffffff1660e01b81526004016200346195949392919062004cd3565b6000604051808303816000875af115801562003481573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620034ab919081019062004535565b905080600081518110620034c357620034c3620044a7565b60200260200101518160018351620034dc919062004628565b81518110620034ef57620034ef620044a7565b6020026020010151945094505050505b94509492505050565b600062003515826200313e565b62003529670de0b6b3a764000086620045d9565b62003535919062004611565b6040516340c10f1960e01b81526001600160a01b03858116600483015260248201839052919250908316906340c10f1990604401600060405180830381600087803b1580156200358457600080fd5b505af115801562003599573d6000803e3d6000fd5b505060d6546001600160a01b03858116911614159150620035d69050578360de6000828254620035ca9190620048e6565b9091555062002a319050565b8360df6000828254620035ea9190620048e6565b90915550509392505050565b60ec5480156200360757806200360b565b61c3505b60ea5490915060ff161562000fcb576000620182b88310620036325750620182b862003646565b818311156200364357508162003646565b50805b620186a0620036568483620045d9565b62003662919062004611565b60da55505050565b6000620036c1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031662003db09092919063ffffffff16565b9050805160001480620036e5575080806020019051810190620036e5919062004d11565b620024d55760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016200107b565b600054610100900460ff16620037705760405162461bcd60e51b81526004016200107b9062004af1565b6033805460ff19169055565b600054610100900460ff16620037a65760405162461bcd60e51b81526004016200107b9062004af1565b620016f462003dc9565b600054610100900460ff16620037da5760405162461bcd60e51b81526004016200107b9062004af1565b620016f462003dfe565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa15801562003835573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200385b919062004642565b9050620038988463095ea7b360e01b85620038778686620048e6565b6040516001600160a01b03909216602483015260448201526064016200249d565b50505050565b6000670de0b6b3a7640000620038b4836200198b565b836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620038f3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003919919062004642565b620039259190620045d9565b62001677919062004611565b6000670de0b6b3a7640000620038b4836200313e565b60335460ff1615620016f45760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016200107b565b60c954806200399c575050565b8082620039a862001b74565b620039b49190620048e6565b111562000fcb5760405162461bcd60e51b81526020600482015260016024820152601960f91b60448201526064016200107b565b6000620039f4620025e5565b60d354909150600160b81b900460ff1662003a705780620186a060ed54620186a062003a21919062004628565b60e05462003a309190620045d9565b62003a3c919062004611565b111562003a705760405162461bcd60e51b81526020600482015260016024820152600d60fa1b60448201526064016200107b565b60e055565b60ef5480158062003aa8575060d7546001600160a01b03848116911614801562003aa8575060d9546001600160a01b0316155b8062003ad6575060d6546001600160a01b03848116911614801562003ad6575060d8546001600160a01b0316155b1562003ae157505050565b6040516370a0823160e01b81523360048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa15801562003b29573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003b4f919062004642565b9050600080821162003b6357600062003b8f565b670de0b6b3a764000062003b77866200313e565b62003b839084620045d9565b62003b8f919062004611565b62003b9b9085620048e6565b60d15490915062003bad8483620045d9565b62003bb9919062004611565b6040516370a0823160e01b815233600482015273aac13a116ea7016689993193fce4badc8038136f906370a0823190602401602060405180830381865afa15801562003c09573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003c2f919062004642565b101562003c505760405162461bcd60e51b81526004016200107b9062004677565b5050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052620038989085906323b872dd60e01b906084016200249d565b60335460ff16620016f45760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016200107b565b6002609754141562003d315760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016200107b565b6002609755565b60cb546040516bffffffffffffffffffffffff193260601b166020820152436034820152605401604051602081830303815290604052805190602001201415620016f45760405162461bcd60e51b81526020600482015260016024820152600760fb1b60448201526064016200107b565b6001609755565b606062003dc1848460008562003e28565b949350505050565b600054610100900460ff1662003df35760405162461bcd60e51b81526004016200107b9062004af1565b620016f43362002b59565b600054610100900460ff1662003da95760405162461bcd60e51b81526004016200107b9062004af1565b60608247101562003e8b5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016200107b565b600080866001600160a01b0316858760405162003ea9919062004d31565b60006040518083038185875af1925050503d806000811462003ee8576040519150601f19603f3d011682016040523d82523d6000602084013e62003eed565b606091505b509150915062003f008783838762003f0b565b979650505050505050565b6060831562003f7c57825162003f74576001600160a01b0385163b62003f745760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016200107b565b508162003dc1565b62003dc1838381511562003f935781518083602001fd5b8060405162461bcd60e51b81526004016200107b919062004d4f565b610e128062004d7b83390190565b620016f462004d64565b60008083601f84011262003fda57600080fd5b5081356001600160401b0381111562003ff257600080fd5b6020830191508360208260051b85010111156200400e57600080fd5b9250929050565b60008060008060008060008060008060a08b8d0312156200403557600080fd5b8a356001600160401b03808211156200404d57600080fd5b6200405b8e838f0162003fc7565b909c509a5060208d01359150808211156200407557600080fd5b620040838e838f0162003fc7565b909a50985060408d01359150808211156200409d57600080fd5b620040ab8e838f0162003fc7565b909850965060608d0135915080821115620040c557600080fd5b620040d38e838f0162003fc7565b909650945060808d0135915080821115620040ed57600080fd5b50620040fc8d828e0162003fc7565b915080935050809150509295989b9194979a5092959850565b6000602080830181845280855180835260408601915060408160051b87010192508387016000805b838110156200419557888603603f19018552825180518088529088019088880190845b818110156200417e5783518352928a0192918a019160010162004160565b50909750505093860193918601916001016200413d565b509398975050505050505050565b80151581146200164657600080fd5b600060208284031215620041c557600080fd5b813562002a3181620041a3565b6001600160a01b03811681146200164657600080fd5b60008060408385031215620041fc57600080fd5b82356200420981620041d2565b946020939093013593505050565b6000602082840312156200422a57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171562004272576200427262004231565b604052919050565b60006001600160401b0382111562004296576200429662004231565b5060051b60200190565b60008060008060008060008060006101208a8c031215620042c057600080fd5b893598506020808b0135620042d581620041d2565b985060408b0135620042e781620041d2565b975060608b0135620042f981620041d2565b965060808b01356200430b81620041d2565b955060a08b01356200431d81620041d2565b945060c08b0135935060e08b013592506101008b01356001600160401b038111156200434857600080fd5b8b01601f81018d136200435a57600080fd5b8035620043716200436b826200427a565b62004247565b81815260059190911b8201830190838101908f8311156200439157600080fd5b928401925b82841015620043bc578335620043ac81620041d2565b8252928401929084019062004396565b80955050505050509295985092959850929598565b60008060408385031215620043e557600080fd5b823591506020830135620043f981620041a3565b809150509250929050565b6000602082840312156200441757600080fd5b813562002a3181620041d2565b600080604083850312156200443857600080fd5b823591506020830135620043f981620041d2565b600081518084526020808501945080840160005b83811015620044875781516001600160a01b03168752958201959082019060010162004460565b509495945050505050565b6020815260006200167460208301846200444c565b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112620044d557600080fd5b8301803591506001600160401b03821115620044f057600080fd5b6020019150368190038213156200400e57600080fd5b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b600060208083850312156200454957600080fd5b82516001600160401b038111156200456057600080fd5b8301601f810185136200457257600080fd5b8051620045836200436b826200427a565b81815260059190911b82018301908381019087831115620045a357600080fd5b928401925b8284101562003f0057835182529284019290840190620045a8565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620045f657620045f6620045c3565b500290565b634e487b7160e01b600052601260045260246000fd5b600082620046235762004623620045fb565b500490565b6000828210156200463d576200463d620045c3565b500390565b6000602082840312156200465557600080fd5b5051919050565b6020808252600190820152600360fc1b604082015260600190565b6020808252600190820152603760f81b604082015260600190565b600060208284031215620046a557600080fd5b815162002a3181620041d2565b60005b83811015620046cf578181015183820152602001620046b5565b83811115620038985750506000910152565b60006001600160401b03831115620046fd57620046fd62004231565b62004712601f8401601f191660200162004247565b90508281528383830111156200472757600080fd5b62002a31836020830184620046b2565b6000602082840312156200474a57600080fd5b81516001600160401b038111156200476157600080fd5b8201601f810184136200477357600080fd5b62003dc184825160208401620046e1565b600081518084526200479e816020860160208601620046b2565b601f01601f19169290920160200192915050565b604081526000620047c7604083018562004784565b8281036020840152620026ec818562004784565b600181815b808511156200481c578160001904821115620048005762004800620045c3565b808516156200480e57918102915b93841c9390800290620047e0565b509250929050565b600082620048355750600162001677565b81620048445750600062001677565b81600181146200485d5760028114620048685762004888565b600191505062001677565b60ff8411156200487c576200487c620045c3565b50506001821b62001677565b5060208310610133831016604e8410600b8410161715620048ad575081810a62001677565b620048b98383620047db565b8060001904821115620048d057620048d0620045c3565b029392505050565b600062001674838362004824565b60008219821115620048fc57620048fc620045c3565b500190565b600060208083850312156200491557600080fd5b82516001600160401b038111156200492c57600080fd5b8301601f810185136200493e57600080fd5b80516200494f6200436b826200427a565b81815260059190911b820183019083810190878311156200496f57600080fd5b928401925b8284101562003f005783516200498a81620041d2565b8252928401929084019062004974565b60006020808385031215620049ae57600080fd5b82516001600160401b0380821115620049c657600080fd5b818501915085601f830112620049db57600080fd5b8151620049ec6200436b826200427a565b81815260059190911b8301840190848101908883111562004a0c57600080fd5b8585015b8381101562004a5f5780518581111562004a2a5760008081fd5b8601603f81018b1362004a3d5760008081fd5b62004a508b8983015160408401620046e1565b84525091860191860162004a10565b5098975050505050505050565b600060001982141562004a835762004a83620045c3565b5060010190565b600080821280156001600160ff1b038490038513161562004aaf5762004aaf620045c3565b600160ff1b839003841281161562004acb5762004acb620045c3565b50500190565b6000600160ff1b82141562004aea5762004aea620045c3565b5060000390565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6000835162004b50818460208801620046b2565b83519083019062004b66818360208801620046b2565b01949350505050565b60008083128015600160ff1b85018412161562004b905762004b90620045c3565b6001600160ff1b038401831381161562004bae5762004bae620045c3565b50500390565b60006001600160ff1b038184138284138082168684048611161562004bdd5762004bdd620045c3565b600160ff1b600087128281168783058912161562004bff5762004bff620045c3565b6000871292508782058712848416161562004c1e5762004c1e620045c3565b8785058712818416161562004c375762004c37620045c3565b505050929093029392505050565b60008262004c575762004c57620045fb565b600160ff1b82146000198414161562004c745762004c74620045c3565b500590565b602081526000825160a0602084015262004c9760c084018262004784565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b85815284602082015260a06040820152600062004cf460a08301866200444c565b6001600160a01b0394909416606083015250608001529392505050565b60006020828403121562004d2457600080fd5b815162002a3181620041a3565b6000825162004d45818460208701620046b2565b9190910192915050565b60208152600062001674602083018462004784565b634e487b7160e01b600052605160045260246000fdfe60806040523480156200001157600080fd5b5060405162000e1238038062000e128339810160408190526200003491620001f4565b8151829082906200004d90600390602085019062000081565b5080516200006390600490602084019062000081565b5050600580546001600160a01b03191633179055506200029b915050565b8280546200008f906200025e565b90600052602060002090601f016020900481019282620000b35760008555620000fe565b82601f10620000ce57805160ff1916838001178555620000fe565b82800160010185558215620000fe579182015b82811115620000fe578251825591602001919060010190620000e1565b506200010c92915062000110565b5090565b5b808211156200010c576000815560010162000111565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014f57600080fd5b81516001600160401b03808211156200016c576200016c62000127565b604051601f8301601f19908116603f0116810190828211818310171562000197576200019762000127565b81604052838152602092508683858801011115620001b457600080fd5b600091505b83821015620001d85785820183015181830184015290820190620001b9565b83821115620001ea5760008385830101525b9695505050505050565b600080604083850312156200020857600080fd5b82516001600160401b03808211156200022057600080fd5b6200022e868387016200013d565b935060208501519150808211156200024557600080fd5b5062000254858286016200013d565b9150509250929050565b600181811c908216806200027357607f821691505b602082108114156200029557634e487b7160e01b600052602260045260246000fd5b50919050565b610b6780620002ab6000396000f3fe608060405234801561001057600080fd5b50600436106100ca5760003560e01c806340c10f191161007c57806340c10f191461018257806370a082311461019757806395d89b41146101c05780639dc29fac146101c8578063a457c2d7146101db578063a9059cbb146101ee578063dd62ed3e1461020157600080fd5b806306fdde03146100cf57806307546172146100ed578063095ea7b31461011857806318160ddd1461013b57806323b872dd1461014d578063313ce56714610160578063395093511461016f575b600080fd5b6100d7610214565b6040516100e491906109a4565b60405180910390f35b600554610100906001600160a01b031681565b6040516001600160a01b0390911681526020016100e4565b61012b610126366004610a15565b6102a6565b60405190151581526020016100e4565b6002545b6040519081526020016100e4565b61012b61015b366004610a3f565b6102be565b604051601281526020016100e4565b61012b61017d366004610a15565b6102e2565b610195610190366004610a15565b610304565b005b61013f6101a5366004610a7b565b6001600160a01b031660009081526020819052604090205490565b6100d7610361565b6101956101d6366004610a15565b610370565b61012b6101e9366004610a15565b6103c4565b61012b6101fc366004610a15565b61043f565b61013f61020f366004610a9d565b61044d565b60606003805461022390610ad0565b80601f016020809104026020016040519081016040528092919081815260200182805461024f90610ad0565b801561029c5780601f106102715761010080835404028352916020019161029c565b820191906000526020600020905b81548152906001019060200180831161027f57829003601f168201915b5050505050905090565b6000336102b4818585610478565b5060019392505050565b6000336102cc85828561059d565b6102d7858585610617565b506001949350505050565b6000336102b48185856102f5838361044d565b6102ff9190610b0b565b610478565b6005546001600160a01b031633146103535760405162461bcd60e51b815260206004820152600d60248201526c0a8a4829c86908a744282aaa89609b1b60448201526064015b60405180910390fd5b61035d82826107bb565b5050565b60606004805461022390610ad0565b6005546001600160a01b031633146103ba5760405162461bcd60e51b815260206004820152600d60248201526c0a8a4829c86908a744282aaa89609b1b604482015260640161034a565b61035d828261087a565b600033816103d2828661044d565b9050838110156104325760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b606482015260840161034a565b6102d78286868403610478565b6000336102b4818585610617565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104da5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161034a565b6001600160a01b03821661053b5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161034a565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60006105a9848461044d565b9050600019811461061157818110156106045760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161034a565b6106118484848403610478565b50505050565b6001600160a01b03831661067b5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161034a565b6001600160a01b0382166106dd5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161034a565b6001600160a01b038316600090815260208190526040902054818110156107555760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b606482015260840161034a565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610611565b6001600160a01b0382166108115760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161034a565b80600260008282546108239190610b0b565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6001600160a01b0382166108da5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161034a565b6001600160a01b0382166000908152602081905260409020548181101561094e5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161034a565b6001600160a01b0383166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610590565b600060208083528351808285015260005b818110156109d1578581018301518582016040015282016109b5565b818111156109e3576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b0381168114610a1057600080fd5b919050565b60008060408385031215610a2857600080fd5b610a31836109f9565b946020939093013593505050565b600080600060608486031215610a5457600080fd5b610a5d846109f9565b9250610a6b602085016109f9565b9150604084013590509250925092565b600060208284031215610a8d57600080fd5b610a96826109f9565b9392505050565b60008060408385031215610ab057600080fd5b610ab9836109f9565b9150610ac7602084016109f9565b90509250929050565b600181811c90821680610ae457607f821691505b60208210811415610b0557634e487b7160e01b600052602260045260246000fd5b50919050565b60008219821115610b2c57634e487b7160e01b600052601160045260246000fd5b50019056fea2646970667358221220a4ff320bee61a8bbf6fca5851081eb415647af1a4d8f34bb4fdcdc9edeabb68064736f6c634300080a0033a2646970667358221220538c10eff7994a1d4ccaafeeffd2b90a180a99cedb985f194e61504238e3e50264736f6c634300080a0033
Deployed Bytecode
0x60806040523480156200001157600080fd5b5060043610620005295760003560e01c80636f47d99b11620002ad578063a8c62e761162000179578063e3e3936811620000df578063efdcd974116200009e578063efdcd9741462000afc578063f2fde38b1462000b13578063f8623d9b1462000b2a578063fc0c546a1462000b41578063fdf4c0dc1462000b55578063fe81a0241462000b5f57600080fd5b8063e3e393681462000a9c578063e70875ad1462000ab0578063e86d8c341462000ac7578063eb120bf41462000ade578063edd636fb1462000af257600080fd5b8063cc1158051162000138578063cc1158051462000a38578063d816f5dc1462000a4f578063dc82697c1462000a66578063ddca3f431462000a70578063dfd5b1c91462000a7a578063e07eace61462000a8557600080fd5b8063a8c62e7614620009df578063b3f0067414620009f3578063b450dfce1462000a07578063bc063e1a1462000a1e578063c9aba3561462000a2857600080fd5b80638f5aa090116200021f5780639af6485411620001de5780639af6485414620009715780639d3ef4b21462000988578063a219d218146200099d578063a27eccc114620009b4578063a3d0bd4814620009be578063a4d66daf14620009d557600080fd5b80638f5aa090146200090b5780639290d427146200092257806392b29be3146200093957806394929dc1146200094357806399abe5e8146200095a57600080fd5b806383975b67116200026c57806383975b6714620008b75780638456cb5914620008c157806387109ffd14620008cb5780638a0dac4a14620008e25780638da5cb5b14620008f957600080fd5b80636f47d99b1462000870578063715018a61462000885578063734d8287146200088f578063747efea114620008995780637509539214620008ad57600080fd5b80632c2a7ca411620003f957806344966ba0116200035f5780635c975abb116200031e5780635c975abb146200081857806362adade514620008245780636373ea69146200082e57806366a4c633146200083857806369fe0e2d14620008425780636cfd1553146200085957600080fd5b806344966ba014620007ba578063452a932014620007ce5780634684059014620007e2578063494347e714620007f957806355c70701146200080357600080fd5b80633f4ba83a11620003b85780633f4ba83a146200075a5780633fc8cef31462000764578063400f7d321462000778578063408f3a30146200078257806340bd61091462000799578063435d44d914620007a357600080fd5b80632c2a7ca414620007025780632cc0800e146200070c5780633403c2fc1462000723578063387af1bd146200072d5780633b28d537146200074157600080fd5b806318dc7195116200049f5780632047782a116200045e5780632047782a146200069f57806325cdd86014620006a957806325f66adf14620006b35780632758db0c14620006bd57806329811ee514620006d45780632a3e4dc214620006eb57600080fd5b806318dc719514620006265780631a7e0ce5146200063d5780631cac6454146200065c5780631cf7a8ff14620006735780631ed4fd97146200068a57600080fd5b80631072cbea11620004ec5780631072cbea14620005c157806312361ac214620005d85780631441a5a914620005e25780631533c31e14620005fb57806315c44b8b146200061257600080fd5b806301d22ccd146200052e57806303311d75146200055f57806306a9a8bf1462000585578063085a2b78146200059e578063088f4b7814620005a8575b600080fd5b60d25462000542906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b620005766200057036600462004015565b62000b69565b60405162000556919062004115565b6200058f60ed5481565b60405190815260200162000556565b6200058f60da5481565b620005bf620005b9366004620041b2565b62000f88565b005b620005bf620005d2366004620041e8565b62000fa5565b6200058f60dc5481565b60e854620005429061010090046001600160a01b031681565b620005bf6200060c36600462004217565b62000fcf565b60d95462000542906001600160a01b031681565b620005bf62000637366004620042a0565b62000fde565b60ea546200064b9060ff1681565b604051901515815260200162000556565b620005bf6200066d36600462004217565b62001602565b620005bf6200068436600462004217565b62001611565b60d3546200064b90600160b81b900460ff1681565b6200058f60e55481565b6200058f62001649565b6200058f60db5481565b6200058f620006ce366004620043d1565b6200165c565b6200058f620006e536600462004404565b6200167d565b62000542620006fc36600462004217565b62001696565b6200058f60ec5481565b6200058f6200071d36600462004424565b620016c1565b620005bf620016de565b60ca5462000542906001600160a01b031681565b6200074b620016f6565b60405162000556919062004492565b620005bf6200175a565b60cd5462000542906001600160a01b031681565b6200058f60dd5481565b620005bf6200079336600462004217565b6200176e565b6200058f60ee5481565b620005bf620007b436600462004217565b6200177d565b60d65462000542906001600160a01b031681565b60d05462000542906001600160a01b031681565b620005bf620007f3366004620041b2565b620017b7565b620005bf620017df565b60d3546200064b90600160a01b900460ff1681565b60335460ff166200064b565b6200058f60de5481565b6200058f60e95481565b6200058f60ef5481565b620005bf6200085336600462004217565b62001815565b620005bf6200086a36600462004404565b62001849565b60d3546200064b90600160b01b900460ff1681565b620005bf62001890565b6200058f60e15481565b60d55462000542906001600160a01b031681565b6200058f60eb5481565b620005bf620018a6565b620005bf620018d4565b620005bf620008dc36600462004217565b620018e8565b620005bf620008f336600462004404565b6200191c565b6065546001600160a01b031662000542565b620005bf6200091c366004620041b2565b62001963565b6200058f6200093336600462004404565b6200198b565b6200058f60e25481565b620005bf6200095436600462004217565b620019e1565b6200058f6200096b36600462004217565b620019f0565b6200058f6200098236600462004217565b62001a60565b60d3546200064b90600160a81b900460ff1681565b6200058f620009ae36600462004404565b62001ad0565b6200058f60d15481565b620005bf620009cf36600462004217565b62001add565b6200058f60c95481565b60d45462000542906001600160a01b031681565b60e45462000542906001600160a01b031681565b6200058f62000a1836600462004217565b62001b12565b6200058f614e2081565b6200058f670de0b6b3a764000081565b620005bf62000a49366004620041b2565b62001b2f565b6200058f62000a6036600462004424565b62001b57565b6200058f62001b74565b6200058f60e35481565b6200058f620186a081565b620005bf62000a96366004620041b2565b62001c74565b60d75462000542906001600160a01b031681565b6200058f62000ac136600462004217565b62001c9c565b620005bf62000ad836600462004217565b62001cb9565b60d85462000542906001600160a01b031681565b6200058f60e65481565b620005bf62000b0d36600462004404565b62001cc8565b620005bf62000b2436600462004404565b62001d0f565b620005bf62000b3b36600462004404565b62001d8b565b60cf5462000542906001600160a01b031681565b6200058f60e05481565b6200058f60df5481565b606062000b7562001e99565b6040805160038082526080820190925290816020015b606081526020019060019003908162000b8b57505060d4549091506001600160a01b03168b8b600381811062000bc55762000bc5620044a7565b905060200201602081019062000bdc9190620041b2565b62000ea35760008c8c600081811062000bf95762000bf9620044a7565b905060200201602081019062000c109190620041b2565b62000e4357816001600160a01b0316638ec71e0c8686600081811062000c3a5762000c3a620044a7565b905060200281019062000c4e9190620044bd565b6040518363ffffffff1660e01b815260040162000c6d92919062004506565b6000604051808303816000875af115801562000c8d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000cb7919081019062004535565b8360028151811062000ccd5762000ccd620044a7565b602002602001018190525062000dfc82888880806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508b8b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508e8e808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c92508b91506001905081811062000dad5762000dad620044a7565b905060200281019062000dc19190620044bd565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062001f0292505050565b8560008151811062000e125762000e12620044a7565b602002602001018660018151811062000e2f5762000e2f620044a7565b602002602001018295508390528390525050505b4360cc55801562000e55578062000e58565b60015b60e75562000e6562002204565b8c8c600281811062000e7b5762000e7b620044a7565b905060200201602081019062000e929190620041b2565b62000ea15762000ea16200236c565b505b60cf5460009062000ebd906001600160a01b0316620023b2565b90506000620186a060e25462000ed262001b74565b62000ede9190620045d9565b62000eea919062004611565b90508082111562000f77576001600160a01b03831663b6b55f2562000f10838562004628565b6040518263ffffffff1660e01b815260040162000f2f91815260200190565b6020604051808303816000875af115801562000f4f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000f75919062004642565b505b5050509a9950505050505050505050565b62000f9262002420565b60ea805460ff1916911515919091179055565b62000faf62002420565b60ca5462000fcb906001600160a01b0384811691168362002470565b5050565b62000fd962002420565b60ee55565b600054610100900460ff161580801562000fff5750600054600160ff909116105b806200101b5750303b1580156200101b575060005460ff166001145b620010845760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015620010a8576000805461ff0019166101001790555b60cf546001600160a01b031615620010e75760405162461bcd60e51b81526020600482015260016024820152603160f81b60448201526064016200107b565b6001600160a01b038616620011105760405162461bcd60e51b81526004016200107b906200465c565b6001600160a01b038516620011395760405162461bcd60e51b81526004016200107b906200465c565b6001600160a01b038916620011625760405162461bcd60e51b81526004016200107b906200465c565b620186a0841115620011885760405162461bcd60e51b81526004016200107b9062004677565b62001192620024da565b6200119f8a89896200250e565b6000856001600160a01b031663747efea16040518163ffffffff1660e01b8152600401602060405180830381865afa158015620011e0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001206919062004692565b90506000816001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001249573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262001273919081019062004737565b9050620012ae60405180604001604052806015815260200174024b23632a1a2279020a0902a3930b731b43290169605d1b815250826200259f565b620012d56040518060400160405280600381526020016241415f60e81b815250836200259f565b604051620012e39062003faf565b620012f0929190620047b2565b604051809103906000f0801580156200130d573d6000803e3d6000fd5b5060d680546001600160a01b0319166001600160a01b0392909216919091179055604080518082019091526015815274024b23632a1a227902121102a3930b731b43290169605d1b60208201526200136690826200259f565b6200138d6040518060400160405280600381526020016242425f60e81b815250836200259f565b6040516200139b9062003faf565b620013a8929190620047b2565b604051809103906000f080158015620013c5573d6000803e3d6000fd5b5060d780546001600160a01b03199081166001600160a01b039384161790915560cf805482168e841690811790915560d4805483168b851617905560d58054831686851617905560d28054909216928b1692909217905560da8790556040805163313ce56760e01b815290516000929163313ce5679160048083019260209291908290030181865afa15801562001460573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001486919062004642565b6200149390600a620048d8565b60d181905560d3805460cd80546001600160a01b03191673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc217905560dc83905560dd8390556107d060e25561190060e655760101017a250d5630b4cf539739df2c5dacb4c659f2488d6001600160b81b031990911617905590506200150d8c89620025cd565b620015198389620025cd565b62001523620025e5565b60e055613a9860e35560e480546001600160a01b031990811673fb3bd022d5dacf95ee28a6b07825d4ff9c5b38141790915560d080546001600160a01b038d16921691909117905560ea805460ff1916600117905561c35060ec5561138860ed55620015ac60d45460d580546001600160a01b0319166001600160a01b03909216919091179055565b5050508015620015f6576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b6200160c62002420565b60ef55565b6200161b62002420565b620186a08160e28190551115620016465760405162461bcd60e51b81526004016200107b9062004677565b50565b600062001657600062002656565b905090565b60006200166862001e99565b620016748383620026f5565b90505b92915050565b6000620016778262001690600062002656565b620027d1565b60ce8181548110620016a757600080fd5b6000918252602090912001546001600160a01b0316905081565b60d754600090620016749084906001600160a01b031684620028ec565b620016e862002a38565b620016f4600062002a5f565b565b606060ce8054806020026020016040519081016040528092919081815260200182805480156200175057602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831162001731575b5050505050905090565b6200176462002a38565b620016f462002aa9565b6200177862002420565b60c955565b6200178762002420565b620186a08160ec8190551115620017b25760405162461bcd60e51b81526004016200107b9062004677565b60ec55565b620017c162002420565b60d38054911515600160b81b0260ff60b81b19909216919091179055565b620017e962002a38565b60d3805460ff60b81b1916600160b81b1790556200180662002204565b60d3805460ff60b81b19169055565b6200181f62002420565b614e208160e38190551115620016465760405162461bcd60e51b81526004016200107b9062004677565b6200185362002420565b60d280546001600160a01b0319166001600160a01b038316908117909155620016465760405162461bcd60e51b81526004016200107b906200465c565b6200189a62002afd565b620016f4600062002b59565b620018b062002420565b620018ba62002aa9565b60d3805463ffffffff60a01b19166201010160a01b179055565b620018de62002a38565b620016f462002bab565b620018f262002420565b620186a08110620019175760405162461bcd60e51b81526004016200107b9062004677565b60ed55565b6200192662002420565b60d080546001600160a01b0319166001600160a01b038316908117909155620016465760405162461bcd60e51b81526004016200107b906200465c565b6200196d62002420565b60d38054911515600160a81b0260ff60a81b19909216919091179055565b60de5460df5460009190620019d884620019a462001b74565b620019b08486620048e6565b60d6546001600160a01b03898116911614620019cd5784620019cf565b855b60da5462002beb565b50949350505050565b620019eb62002420565b60e655565b6000620019ff60335460ff1690565b158062001a15575060d354600160a81b900460ff165b62001a475760405162461bcd60e51b81526020600482015260016024820152603360f81b60448201526064016200107b565b60d754620016779083906001600160a01b031662002f11565b600062001a6f60335460ff1690565b158062001a85575060d354600160a01b900460ff165b62001ab75760405162461bcd60e51b81526020600482015260016024820152603360f81b60448201526064016200107b565b60d654620016779083906001600160a01b031662002f11565b600062001677826200313e565b62001ae762002420565b620186a08160da8190551115620016465760405162461bcd60e51b81526004016200107b9062004677565b60d654600090620016779083906001600160a01b031683620028ec565b62001b3962002420565b60d38054911515600160a01b0260ff60a01b19909216919091179055565b60d654600090620016749084906001600160a01b031684620028ec565b60d5546040805163313ce56760e01b815290516000926001600160a01b0316918391839163313ce5679160048083019260209291908290030181865afa15801562001bc3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001be9919062004642565b905060e15462001bf8620031d9565b60cf5462001c0f906001600160a01b0316620023b2565b62001c1c84600a620048d8565b62001c26620025e5565b62001c3187620023b2565b62001c3d9190620045d9565b62001c49919062004611565b62001c559190620048e6565b62001c61919062004628565b62001c6d919062004628565b9250505090565b62001c7e62002420565b60d38054911515600160b01b0260ff60b01b19909216919091179055565b60d754600090620016779083906001600160a01b031683620028ec565b62001cc362002420565b60eb55565b62001cd262002420565b60e480546001600160a01b0319166001600160a01b038316908117909155620016465760405162461bcd60e51b81526004016200107b906200465c565b62001d1962002afd565b6001600160a01b03811662001d805760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016200107b565b620016468162002b59565b62001d9562002420565b60d65460d7546001600160a01b03918216918381169116148062001dca5750806001600160a01b0316826001600160a01b0316145b62001dfc5760405162461bcd60e51b81526020600482015260016024820152603960f81b60448201526064016200107b565b806001600160a01b0316826001600160a01b0316141562001e585760d8546001600160a01b03161562001e3157600062001e34565b60015b60d880546001600160a01b0319166001600160a01b03929092169190911790555050565b60d9546001600160a01b03161562001e7257600062001e75565b60015b60d980546001600160a01b0319166001600160a01b03929092169190911790555050565b60d2546001600160a01b031633148062001ed057506065546001600160a01b03165b6001600160a01b0316336001600160a01b0316145b620016f45760405162461bcd60e51b81526020600482015260016024820152601b60f91b60448201526064016200107b565b606080600080886001600160a01b031663c4f59f9b6040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001f47573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262001f71919081019062004901565b905060008082516001600160401b0381111562001f925762001f9262004231565b60405190808252806020026020018201604052801562001fc757816020015b606081526020019060019003908162001fb15790505b5087519091501562001fec578680602001905181019062001fe991906200499a565b90505b8251806001600160401b0381111562002009576200200962004231565b60405190808252806020026020018201604052801562002033578160200160208202803683370190505b509650806001600160401b0381111562002051576200205162004231565b6040519080825280602002602001820160405280156200207b578160200160208202803683370190505b50955060005b81811015620021f4578481815181106200209f576200209f620044a7565b60200260200101519350898181518110620020be57620020be620044a7565b602002602001015115620020d257620021e1565b6001600160a01b038416734da27a545c0c5b758a6ba100e3a049001de870f514156200211057737fc66500c84a76ad7e9c93437bfc5ac33e2ddae993505b62002172848483815181106200212a576200212a620044a7565b60200260200101518e8481518110620021475762002147620044a7565b60200260200101518e8581518110620021645762002164620044a7565b60200260200101516200323b565b898381518110620021875762002187620044a7565b60200260200101898481518110620021a357620021a3620044a7565b6020026020010182815250828152505050868181518110620021c957620021c9620044a7565b602002602001015186620021de9190620048e6565b95505b620021ec8162004a6c565b905062002081565b5050505050955095509592505050565b60de5460df546000620022188284620048e6565b905060006200222662001b74565b60da54909150828211156200227a5760e354620186a09062002249858562004628565b620022559190620045d9565b62002261919062004611565b60e16000828254620022749190620048e6565b90915550505b60d65460009081906200229a906001600160a01b031685878a8762002beb565b60d75491935091506000908190620022bf906001600160a01b031687898b8962002beb565b9092509050620022d0838a62004a8a565b60de55600081128015620022ee575087620022eb8262004ad1565b12155b156200234a5760d354600160b81b900460ff16620023335760405162461bcd60e51b81526020600482015260016024820152600d60fa1b60448201526064016200107b565b600060df5562002344600162002a5f565b6200235a565b62002356818962004a8a565b60df555b5060dc929092555060dd555050505050565b60e1548015620016465760e45460d654620023969183916001600160a01b03918216911662003508565b50600060e15562001646620023ac600162002656565b620035f6565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015620023fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001677919062004642565b33620024346065546001600160a01b031690565b6001600160a01b031614620016f45760405162461bcd60e51b81526020600482015260016024820152601b60f91b60448201526064016200107b565b6040516001600160a01b038316602482015260448101829052620024d590849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526200366a565b505050565b600054610100900460ff16620025045760405162461bcd60e51b81526004016200107b9062004af1565b620016f462003746565b6001600160a01b038216620025375760405162461bcd60e51b81526004016200107b906200465c565b6001600160a01b038116620025605760405162461bcd60e51b81526004016200107b906200465c565b6200256a6200377c565b62002574620037b0565b60c983905560ca80546001600160a01b0319166001600160a01b038416179055620024d58162001d0f565b60608282604051602001620025b692919062004b3c565b604051602081830303815290604052905092915050565b62000fcb6001600160a01b03831682600019620037e4565b60d4546040805163501ad8ff60e11b815290516000926001600160a01b03169163a035b1fe9160048083019260209291908290030181865afa15801562002630573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001657919062004642565b600062003fbd826200266c576200389e62002671565b620039315b60d65490915060009062002691906001600160a01b031663ffffffff8416565b60d754909150600090620026b1906001600160a01b031663ffffffff8516565b620026bd9083620048e6565b905080620026d057506000949350505050565b80620026e0620186a084620045d9565b620026ec919062004611565b95945050505050565b60d45460405163852a12e360e01b8152600481018490526000916001600160a01b03169063852a12e3906024016020604051808303816000875af115801562002742573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002768919062004642565b90508115620027c15760eb54806200277e575060645b836200278b8284620048e6565b1015620027bf5760405162461bcd60e51b81526020600482015260016024820152603560f81b60448201526064016200107b565b505b8281111562001677575090919050565b60008060d460009054906101000a90046001600160a01b03166001600160a01b031663845bc8046040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002828573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200284e919062004642565b60da5460d654919250906001600160a01b03868116911614846200288757806200287957826200287c565b60005b935050505062001677565b80620028c9576200289c85620186a062004628565b620028ab83620186a062004628565b620028b79085620045d9565b620028c3919062004611565b620028e2565b84620028d68385620045d9565b620028e2919062004611565b9695505050505050565b6000620028f862003947565b83620029045762002a31565b6200290f846200398f565b620029546040516bffffffffffffffffffffffff193260601b16602082015243603482015260540160408051601f19818403018152919052805160209091012060cb55565b6200295e620039e8565b6200296862002204565b62002974838562003a75565b60cf546001600160a01b031660006200298d82620023b2565b9050620029a66001600160a01b03831633308962003c57565b620029ca81620029b684620023b2565b620029c2919062004628565b338762003508565b9250620029dc620023ac600162002656565b6001600160a01b0384161562002a2e57604080518781526001600160a01b03861660208201527f496d589d8b7eb829a8d7b30e24a326ac33991f5cea96429b69231a6b15b54b1d910160405180910390a15b50505b9392505050565b60d0546001600160a01b031633148062001ed057506065546001600160a01b031662001ebb565b62002a6962002bab565b60d3805460ff60b01b1962ff00ff60a81b19931515600160a01b029390931663ff00ffff60a01b1990911617600160b81b1791909116600160b01b179055565b62002ab362003c91565b6033805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6065546001600160a01b03163314620016f45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016200107b565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b62002bb562003947565b6033805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25862002ae03390565b6000806000876001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002c2f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002c55919062004642565b905085158062002c63575080155b1562002c7857505060d1549050600062002f07565b600062002c86878962004b6f565b90508062002ca75762002c99896200313e565b600093509350505062002f07565b600081131562002ce057620186a060e3548262002cc5919062004bb4565b62002cd1919062004c45565b62002cdd908262004b6f565b90505b60d65460d7546001600160a01b0391821691908116908b1682148062002d07578262002d09565b815b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002d47573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002d6d919062004642565b62002d7b5783955062002ed1565b600084131562002dd3576000620186a062002d978a8262004628565b62002da3908762004bb4565b62002daf919062004c45565b90508162002dbe578062002dca565b62002dca818662004b6f565b96505062002ed1565b620186a08a60ee5462002de79190620045d9565b62002df3919062004611565b62002dfe8562004ad1565b1162002e575760df5460de5460009062002e1a908390620048e6565b62002e26838862004bb4565b62002e32919062004c45565b90508262002e41578062002e4d565b62002e4d818762004b6f565b9750505062002ed1565b60008162002e66578962002e72565b62002e728a8c62004628565b9050600062002e82868362004a8a565b9050600081131562002ea6578262002e9b578562002e9e565b60005b975062002ece565b8262002eca57600062002eb98362004ad1565b985098505050505050505062002f07565b8097505b50505b84670de0b6b3a764000062002ee7888c62004a8a565b62002ef39190620045d9565b62002eff919062004611565b965050505050505b9550959350505050565b600062002f1d62003cdc565b62002f2762003d38565b62002f31620039e8565b62002f3b62002204565b8262002faf576040516370a0823160e01b81523360048201526001600160a01b038316906370a0823190602401602060405180830381865afa15801562002f86573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002fac919062004642565b92505b8262002fcf5760405162461bcd60e51b81526004016200107b906200465c565b60cf546001600160a01b0316600062002fe882620023b2565b9050670de0b6b3a764000062002ffe856200313e565b6200300a9087620045d9565b62003016919062004611565b925082818111156200305557816200304662003033828762004628565b60d354600160b01b900460ff16620026f5565b620030529190620048e6565b93505b604051632770a7eb60e21b8152336004820152602481018790526001600160a01b03861690639dc29fac90604401600060405180830381600087803b1580156200309e57600080fd5b505af1158015620030b3573d6000803e3d6000fd5b505060d6546001600160a01b03888116911614159150620030f09050578060de6000828254620030e4919062004628565b909155506200310a9050565b8060df600082825462003104919062004628565b90915550505b6200311a620023ac600162002656565b620031306001600160a01b038416338662002470565b505050620016776001609755565b6000816001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200317f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620031a5919062004642565b620031b257505060d15490565b60d6546001600160a01b03838116911614620031d15760dd5462001677565b505060dc5490565b60e65460cc54600091908290620031f1904362004628565b60e7549091506001811180156200320757508282105b156200323557826200321a838262004628565b620032269083620045d9565b62003232919062004611565b93505b50505090565b6000808362003252576200324f86620023b2565b93505b836200326457506000905080620034ff565b8451156200334e5773e592427a0aece92de3edee1f18e0157c05861564620032976001600160a01b0388168287620037e4565b6040805160a0810182528781523060208201526000918101620032bc426064620048e6565b815260200187815260200186815250905085826001600160a01b031663c04b8d59836040518263ffffffff1660e01b8152600401620032fc919062004c79565b6020604051808303816000875af11580156200331c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003342919062004642565b935093505050620034ff565b60d3546001600160a01b03908116906200336c9088168287620037e4565b60408051600380825260808201909252600091602082016060803683370190505090508781600081518110620033a657620033a6620044a7565b6001600160a01b03928316602091820292909201015260cd54825191169082906001908110620033da57620033da620044a7565b6001600160a01b03928316602091820292909201015260cf548251911690829060029081106200340e576200340e620044a7565b6001600160a01b03928316602091820292909201015260009083166338ed1739888885306200343f426064620048e6565b6040518663ffffffff1660e01b81526004016200346195949392919062004cd3565b6000604051808303816000875af115801562003481573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620034ab919081019062004535565b905080600081518110620034c357620034c3620044a7565b60200260200101518160018351620034dc919062004628565b81518110620034ef57620034ef620044a7565b6020026020010151945094505050505b94509492505050565b600062003515826200313e565b62003529670de0b6b3a764000086620045d9565b62003535919062004611565b6040516340c10f1960e01b81526001600160a01b03858116600483015260248201839052919250908316906340c10f1990604401600060405180830381600087803b1580156200358457600080fd5b505af115801562003599573d6000803e3d6000fd5b505060d6546001600160a01b03858116911614159150620035d69050578360de6000828254620035ca9190620048e6565b9091555062002a319050565b8360df6000828254620035ea9190620048e6565b90915550509392505050565b60ec5480156200360757806200360b565b61c3505b60ea5490915060ff161562000fcb576000620182b88310620036325750620182b862003646565b818311156200364357508162003646565b50805b620186a0620036568483620045d9565b62003662919062004611565b60da55505050565b6000620036c1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031662003db09092919063ffffffff16565b9050805160001480620036e5575080806020019051810190620036e5919062004d11565b620024d55760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016200107b565b600054610100900460ff16620037705760405162461bcd60e51b81526004016200107b9062004af1565b6033805460ff19169055565b600054610100900460ff16620037a65760405162461bcd60e51b81526004016200107b9062004af1565b620016f462003dc9565b600054610100900460ff16620037da5760405162461bcd60e51b81526004016200107b9062004af1565b620016f462003dfe565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa15801562003835573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200385b919062004642565b9050620038988463095ea7b360e01b85620038778686620048e6565b6040516001600160a01b03909216602483015260448201526064016200249d565b50505050565b6000670de0b6b3a7640000620038b4836200198b565b836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620038f3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003919919062004642565b620039259190620045d9565b62001677919062004611565b6000670de0b6b3a7640000620038b4836200313e565b60335460ff1615620016f45760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016200107b565b60c954806200399c575050565b8082620039a862001b74565b620039b49190620048e6565b111562000fcb5760405162461bcd60e51b81526020600482015260016024820152601960f91b60448201526064016200107b565b6000620039f4620025e5565b60d354909150600160b81b900460ff1662003a705780620186a060ed54620186a062003a21919062004628565b60e05462003a309190620045d9565b62003a3c919062004611565b111562003a705760405162461bcd60e51b81526020600482015260016024820152600d60fa1b60448201526064016200107b565b60e055565b60ef5480158062003aa8575060d7546001600160a01b03848116911614801562003aa8575060d9546001600160a01b0316155b8062003ad6575060d6546001600160a01b03848116911614801562003ad6575060d8546001600160a01b0316155b1562003ae157505050565b6040516370a0823160e01b81523360048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa15801562003b29573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003b4f919062004642565b9050600080821162003b6357600062003b8f565b670de0b6b3a764000062003b77866200313e565b62003b839084620045d9565b62003b8f919062004611565b62003b9b9085620048e6565b60d15490915062003bad8483620045d9565b62003bb9919062004611565b6040516370a0823160e01b815233600482015273aac13a116ea7016689993193fce4badc8038136f906370a0823190602401602060405180830381865afa15801562003c09573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003c2f919062004642565b101562003c505760405162461bcd60e51b81526004016200107b9062004677565b5050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052620038989085906323b872dd60e01b906084016200249d565b60335460ff16620016f45760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016200107b565b6002609754141562003d315760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016200107b565b6002609755565b60cb546040516bffffffffffffffffffffffff193260601b166020820152436034820152605401604051602081830303815290604052805190602001201415620016f45760405162461bcd60e51b81526020600482015260016024820152600760fb1b60448201526064016200107b565b6001609755565b606062003dc1848460008562003e28565b949350505050565b600054610100900460ff1662003df35760405162461bcd60e51b81526004016200107b9062004af1565b620016f43362002b59565b600054610100900460ff1662003da95760405162461bcd60e51b81526004016200107b9062004af1565b60608247101562003e8b5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016200107b565b600080866001600160a01b0316858760405162003ea9919062004d31565b60006040518083038185875af1925050503d806000811462003ee8576040519150601f19603f3d011682016040523d82523d6000602084013e62003eed565b606091505b509150915062003f008783838762003f0b565b979650505050505050565b6060831562003f7c57825162003f74576001600160a01b0385163b62003f745760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016200107b565b508162003dc1565b62003dc1838381511562003f935781518083602001fd5b8060405162461bcd60e51b81526004016200107b919062004d4f565b610e128062004d7b83390190565b620016f462004d64565b60008083601f84011262003fda57600080fd5b5081356001600160401b0381111562003ff257600080fd5b6020830191508360208260051b85010111156200400e57600080fd5b9250929050565b60008060008060008060008060008060a08b8d0312156200403557600080fd5b8a356001600160401b03808211156200404d57600080fd5b6200405b8e838f0162003fc7565b909c509a5060208d01359150808211156200407557600080fd5b620040838e838f0162003fc7565b909a50985060408d01359150808211156200409d57600080fd5b620040ab8e838f0162003fc7565b909850965060608d0135915080821115620040c557600080fd5b620040d38e838f0162003fc7565b909650945060808d0135915080821115620040ed57600080fd5b50620040fc8d828e0162003fc7565b915080935050809150509295989b9194979a5092959850565b6000602080830181845280855180835260408601915060408160051b87010192508387016000805b838110156200419557888603603f19018552825180518088529088019088880190845b818110156200417e5783518352928a0192918a019160010162004160565b50909750505093860193918601916001016200413d565b509398975050505050505050565b80151581146200164657600080fd5b600060208284031215620041c557600080fd5b813562002a3181620041a3565b6001600160a01b03811681146200164657600080fd5b60008060408385031215620041fc57600080fd5b82356200420981620041d2565b946020939093013593505050565b6000602082840312156200422a57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171562004272576200427262004231565b604052919050565b60006001600160401b0382111562004296576200429662004231565b5060051b60200190565b60008060008060008060008060006101208a8c031215620042c057600080fd5b893598506020808b0135620042d581620041d2565b985060408b0135620042e781620041d2565b975060608b0135620042f981620041d2565b965060808b01356200430b81620041d2565b955060a08b01356200431d81620041d2565b945060c08b0135935060e08b013592506101008b01356001600160401b038111156200434857600080fd5b8b01601f81018d136200435a57600080fd5b8035620043716200436b826200427a565b62004247565b81815260059190911b8201830190838101908f8311156200439157600080fd5b928401925b82841015620043bc578335620043ac81620041d2565b8252928401929084019062004396565b80955050505050509295985092959850929598565b60008060408385031215620043e557600080fd5b823591506020830135620043f981620041a3565b809150509250929050565b6000602082840312156200441757600080fd5b813562002a3181620041d2565b600080604083850312156200443857600080fd5b823591506020830135620043f981620041d2565b600081518084526020808501945080840160005b83811015620044875781516001600160a01b03168752958201959082019060010162004460565b509495945050505050565b6020815260006200167460208301846200444c565b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112620044d557600080fd5b8301803591506001600160401b03821115620044f057600080fd5b6020019150368190038213156200400e57600080fd5b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b600060208083850312156200454957600080fd5b82516001600160401b038111156200456057600080fd5b8301601f810185136200457257600080fd5b8051620045836200436b826200427a565b81815260059190911b82018301908381019087831115620045a357600080fd5b928401925b8284101562003f0057835182529284019290840190620045a8565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620045f657620045f6620045c3565b500290565b634e487b7160e01b600052601260045260246000fd5b600082620046235762004623620045fb565b500490565b6000828210156200463d576200463d620045c3565b500390565b6000602082840312156200465557600080fd5b5051919050565b6020808252600190820152600360fc1b604082015260600190565b6020808252600190820152603760f81b604082015260600190565b600060208284031215620046a557600080fd5b815162002a3181620041d2565b60005b83811015620046cf578181015183820152602001620046b5565b83811115620038985750506000910152565b60006001600160401b03831115620046fd57620046fd62004231565b62004712601f8401601f191660200162004247565b90508281528383830111156200472757600080fd5b62002a31836020830184620046b2565b6000602082840312156200474a57600080fd5b81516001600160401b038111156200476157600080fd5b8201601f810184136200477357600080fd5b62003dc184825160208401620046e1565b600081518084526200479e816020860160208601620046b2565b601f01601f19169290920160200192915050565b604081526000620047c7604083018562004784565b8281036020840152620026ec818562004784565b600181815b808511156200481c578160001904821115620048005762004800620045c3565b808516156200480e57918102915b93841c9390800290620047e0565b509250929050565b600082620048355750600162001677565b81620048445750600062001677565b81600181146200485d5760028114620048685762004888565b600191505062001677565b60ff8411156200487c576200487c620045c3565b50506001821b62001677565b5060208310610133831016604e8410600b8410161715620048ad575081810a62001677565b620048b98383620047db565b8060001904821115620048d057620048d0620045c3565b029392505050565b600062001674838362004824565b60008219821115620048fc57620048fc620045c3565b500190565b600060208083850312156200491557600080fd5b82516001600160401b038111156200492c57600080fd5b8301601f810185136200493e57600080fd5b80516200494f6200436b826200427a565b81815260059190911b820183019083810190878311156200496f57600080fd5b928401925b8284101562003f005783516200498a81620041d2565b8252928401929084019062004974565b60006020808385031215620049ae57600080fd5b82516001600160401b0380821115620049c657600080fd5b818501915085601f830112620049db57600080fd5b8151620049ec6200436b826200427a565b81815260059190911b8301840190848101908883111562004a0c57600080fd5b8585015b8381101562004a5f5780518581111562004a2a5760008081fd5b8601603f81018b1362004a3d5760008081fd5b62004a508b8983015160408401620046e1565b84525091860191860162004a10565b5098975050505050505050565b600060001982141562004a835762004a83620045c3565b5060010190565b600080821280156001600160ff1b038490038513161562004aaf5762004aaf620045c3565b600160ff1b839003841281161562004acb5762004acb620045c3565b50500190565b6000600160ff1b82141562004aea5762004aea620045c3565b5060000390565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6000835162004b50818460208801620046b2565b83519083019062004b66818360208801620046b2565b01949350505050565b60008083128015600160ff1b85018412161562004b905762004b90620045c3565b6001600160ff1b038401831381161562004bae5762004bae620045c3565b50500390565b60006001600160ff1b038184138284138082168684048611161562004bdd5762004bdd620045c3565b600160ff1b600087128281168783058912161562004bff5762004bff620045c3565b6000871292508782058712848416161562004c1e5762004c1e620045c3565b8785058712818416161562004c375762004c37620045c3565b505050929093029392505050565b60008262004c575762004c57620045fb565b600160ff1b82146000198414161562004c745762004c74620045c3565b500590565b602081526000825160a0602084015262004c9760c084018262004784565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b85815284602082015260a06040820152600062004cf460a08301866200444c565b6001600160a01b0394909416606083015250608001529392505050565b60006020828403121562004d2457600080fd5b815162002a3181620041a3565b6000825162004d45818460208701620046b2565b9190910192915050565b60208152600062001674602083018462004784565b634e487b7160e01b600052605160045260246000fdfe60806040523480156200001157600080fd5b5060405162000e1238038062000e128339810160408190526200003491620001f4565b8151829082906200004d90600390602085019062000081565b5080516200006390600490602084019062000081565b5050600580546001600160a01b03191633179055506200029b915050565b8280546200008f906200025e565b90600052602060002090601f016020900481019282620000b35760008555620000fe565b82601f10620000ce57805160ff1916838001178555620000fe565b82800160010185558215620000fe579182015b82811115620000fe578251825591602001919060010190620000e1565b506200010c92915062000110565b5090565b5b808211156200010c576000815560010162000111565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014f57600080fd5b81516001600160401b03808211156200016c576200016c62000127565b604051601f8301601f19908116603f0116810190828211818310171562000197576200019762000127565b81604052838152602092508683858801011115620001b457600080fd5b600091505b83821015620001d85785820183015181830184015290820190620001b9565b83821115620001ea5760008385830101525b9695505050505050565b600080604083850312156200020857600080fd5b82516001600160401b03808211156200022057600080fd5b6200022e868387016200013d565b935060208501519150808211156200024557600080fd5b5062000254858286016200013d565b9150509250929050565b600181811c908216806200027357607f821691505b602082108114156200029557634e487b7160e01b600052602260045260246000fd5b50919050565b610b6780620002ab6000396000f3fe608060405234801561001057600080fd5b50600436106100ca5760003560e01c806340c10f191161007c57806340c10f191461018257806370a082311461019757806395d89b41146101c05780639dc29fac146101c8578063a457c2d7146101db578063a9059cbb146101ee578063dd62ed3e1461020157600080fd5b806306fdde03146100cf57806307546172146100ed578063095ea7b31461011857806318160ddd1461013b57806323b872dd1461014d578063313ce56714610160578063395093511461016f575b600080fd5b6100d7610214565b6040516100e491906109a4565b60405180910390f35b600554610100906001600160a01b031681565b6040516001600160a01b0390911681526020016100e4565b61012b610126366004610a15565b6102a6565b60405190151581526020016100e4565b6002545b6040519081526020016100e4565b61012b61015b366004610a3f565b6102be565b604051601281526020016100e4565b61012b61017d366004610a15565b6102e2565b610195610190366004610a15565b610304565b005b61013f6101a5366004610a7b565b6001600160a01b031660009081526020819052604090205490565b6100d7610361565b6101956101d6366004610a15565b610370565b61012b6101e9366004610a15565b6103c4565b61012b6101fc366004610a15565b61043f565b61013f61020f366004610a9d565b61044d565b60606003805461022390610ad0565b80601f016020809104026020016040519081016040528092919081815260200182805461024f90610ad0565b801561029c5780601f106102715761010080835404028352916020019161029c565b820191906000526020600020905b81548152906001019060200180831161027f57829003601f168201915b5050505050905090565b6000336102b4818585610478565b5060019392505050565b6000336102cc85828561059d565b6102d7858585610617565b506001949350505050565b6000336102b48185856102f5838361044d565b6102ff9190610b0b565b610478565b6005546001600160a01b031633146103535760405162461bcd60e51b815260206004820152600d60248201526c0a8a4829c86908a744282aaa89609b1b60448201526064015b60405180910390fd5b61035d82826107bb565b5050565b60606004805461022390610ad0565b6005546001600160a01b031633146103ba5760405162461bcd60e51b815260206004820152600d60248201526c0a8a4829c86908a744282aaa89609b1b604482015260640161034a565b61035d828261087a565b600033816103d2828661044d565b9050838110156104325760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b606482015260840161034a565b6102d78286868403610478565b6000336102b4818585610617565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104da5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161034a565b6001600160a01b03821661053b5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161034a565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60006105a9848461044d565b9050600019811461061157818110156106045760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161034a565b6106118484848403610478565b50505050565b6001600160a01b03831661067b5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161034a565b6001600160a01b0382166106dd5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161034a565b6001600160a01b038316600090815260208190526040902054818110156107555760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b606482015260840161034a565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610611565b6001600160a01b0382166108115760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161034a565b80600260008282546108239190610b0b565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6001600160a01b0382166108da5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161034a565b6001600160a01b0382166000908152602081905260409020548181101561094e5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161034a565b6001600160a01b0383166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610590565b600060208083528351808285015260005b818110156109d1578581018301518582016040015282016109b5565b818111156109e3576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b0381168114610a1057600080fd5b919050565b60008060408385031215610a2857600080fd5b610a31836109f9565b946020939093013593505050565b600080600060608486031215610a5457600080fd5b610a5d846109f9565b9250610a6b602085016109f9565b9150604084013590509250925092565b600060208284031215610a8d57600080fd5b610a96826109f9565b9392505050565b60008060408385031215610ab057600080fd5b610ab9836109f9565b9150610ac7602084016109f9565b90509250929050565b600181811c90821680610ae457607f821691505b60208210811415610b0557634e487b7160e01b600052602260045260246000fd5b50919050565b60008219821115610b2c57634e487b7160e01b600052601160045260246000fd5b50019056fea2646970667358221220a4ff320bee61a8bbf6fca5851081eb415647af1a4d8f34bb4fdcdc9edeabb68064736f6c634300080a0033a2646970667358221220538c10eff7994a1d4ccaafeeffd2b90a180a99cedb985f194e61504238e3e50264736f6c634300080a0033
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.