Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 25 from a total of 96 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Deploy Vault | 20143586 | 625 days ago | IN | 0 ETH | 0.00366747 | ||||
| Deploy Vault | 20134469 | 627 days ago | IN | 0 ETH | 0.0140318 | ||||
| Deploy Vault | 20109293 | 630 days ago | IN | 0 ETH | 0.00382154 | ||||
| Deploy Vault | 20051519 | 638 days ago | IN | 0 ETH | 0.00545197 | ||||
| Deploy Vault | 19951803 | 652 days ago | IN | 0 ETH | 0.00389556 | ||||
| Deploy Vault | 19901085 | 659 days ago | IN | 0 ETH | 0.004661 | ||||
| Deploy Vault | 19894435 | 660 days ago | IN | 0 ETH | 0.00544309 | ||||
| Deploy Vault | 19886407 | 661 days ago | IN | 0 ETH | 0.00385223 | ||||
| Deploy Vault | 19829923 | 669 days ago | IN | 0 ETH | 0.00502846 | ||||
| Deploy Vault | 19765416 | 678 days ago | IN | 0 ETH | 0.00908315 | ||||
| Deploy Vault | 19751722 | 680 days ago | IN | 0 ETH | 0.00746267 | ||||
| Deploy Vault | 19735358 | 682 days ago | IN | 0 ETH | 0.0089503 | ||||
| Deploy Vault | 19735285 | 682 days ago | IN | 0 ETH | 0.00767657 | ||||
| Deploy Vault | 19551798 | 708 days ago | IN | 0 ETH | 0.02597605 | ||||
| Deploy Vault | 19239506 | 752 days ago | IN | 0 ETH | 0.0434204 | ||||
| Deploy Vault | 19075227 | 775 days ago | IN | 0 ETH | 0.01408704 | ||||
| Deploy Vault | 18928348 | 796 days ago | IN | 0 ETH | 0.11388022 | ||||
| Nominate New Own... | 18840520 | 808 days ago | IN | 0 ETH | 0.00219871 | ||||
| Deploy Vault | 18823194 | 810 days ago | IN | 0 ETH | 0.12884196 | ||||
| Deploy Vault | 18690650 | 829 days ago | IN | 0 ETH | 0.04516108 | ||||
| Deploy Vault | 18626944 | 838 days ago | IN | 0 ETH | 0.04229207 | ||||
| Deploy Vault | 18620985 | 839 days ago | IN | 0 ETH | 0.11200484 | ||||
| Deploy Vault | 18620969 | 839 days ago | IN | 0 ETH | 0.10354056 | ||||
| Deploy Vault | 18620954 | 839 days ago | IN | 0 ETH | 0.09134582 | ||||
| Deploy Vault | 18620927 | 839 days ago | IN | 0 ETH | 0.06604466 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
VaultController
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.15
pragma solidity ^0.8.15;
import {SafeERC20Upgradeable as SafeERC20} from "openzeppelin-contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import {Owned} from "../utils/Owned.sol";
import {IVault, VaultInitParams, VaultFees, IERC4626, IERC20} from "../interfaces/vault/IVault.sol";
import {IMultiRewardStaking} from "../interfaces/IMultiRewardStaking.sol";
import {IMultiRewardEscrow} from "../interfaces/IMultiRewardEscrow.sol";
import {IDeploymentController, ICloneRegistry} from "../interfaces/vault/IDeploymentController.sol";
import {ITemplateRegistry, Template} from "../interfaces/vault/ITemplateRegistry.sol";
import {IPermissionRegistry, Permission} from "../interfaces/vault/IPermissionRegistry.sol";
import {IVaultRegistry, VaultMetadata} from "../interfaces/vault/IVaultRegistry.sol";
import {IAdminProxy} from "../interfaces/vault/IAdminProxy.sol";
import {IStrategy} from "../interfaces/vault/IStrategy.sol";
import {IAdapter} from "../interfaces/vault/IAdapter.sol";
import {IPausable} from "../interfaces/IPausable.sol";
import {DeploymentArgs} from "../interfaces/vault/IVaultController.sol";
/**
* @title VaultController
* @author RedVeil
* @notice Admin contract for the vault ecosystem.
*
* Deploys Vaults, Adapter, Strategies and Staking contracts.
* Calls admin functions on deployed contracts.
*/
contract VaultController is Owned {
using SafeERC20 for IERC20;
/*//////////////////////////////////////////////////////////////
IMMUTABLES
//////////////////////////////////////////////////////////////*/
bytes32 public immutable VAULT = "Vault";
bytes32 public immutable ADAPTER = "Adapter";
bytes32 public immutable STRATEGY = "Strategy";
bytes32 public immutable STAKING = "Staking";
bytes4 internal immutable DEPLOY_SIG =
bytes4(keccak256("deploy(bytes32,bytes32,bytes)"));
/**
* @notice Constructor of this contract.
* @param _owner Owner of the contract. Controls management functions.
* @param _adminProxy `AdminProxy` ownes contracts in the vault ecosystem.
* @param _deploymentController `DeploymentController` with auxiliary deployment contracts.
* @param _vaultRegistry `VaultRegistry` to safe vault metadata.
* @param _permissionRegistry `permissionRegistry` to add endorsements and rejections.
* @param _escrow `MultiRewardEscrow` To escrow rewards of staking contracts.
*/
constructor(
address _owner,
IAdminProxy _adminProxy,
IDeploymentController _deploymentController,
IVaultRegistry _vaultRegistry,
IPermissionRegistry _permissionRegistry,
IMultiRewardEscrow _escrow
) Owned(_owner) {
adminProxy = _adminProxy;
vaultRegistry = _vaultRegistry;
permissionRegistry = _permissionRegistry;
escrow = _escrow;
_setDeploymentController(_deploymentController);
activeTemplateId[STAKING] = "MultiRewardStaking";
activeTemplateId[VAULT] = "V1";
}
/*//////////////////////////////////////////////////////////////
VAULT DEPLOYMENT LOGIC
//////////////////////////////////////////////////////////////*/
event VaultDeployed(
address indexed vault,
address indexed staking,
address indexed adapter
);
error InvalidConfig();
/**
* @notice Deploy a new Vault. Optionally with an Adapter and Staking. Caller must be owner.
* @param vaultData Vault init params.
* @param adapterData Encoded adapter init data.
* @param strategyData Encoded strategy init data.
* @param deployStaking Should we deploy a staking contract for the vault?
* @param rewardsData Encoded data to add a rewards to the staking contract
* @param metadata Vault metadata for the `VaultRegistry` (Will be used by the frontend for additional informations)
* @param initialDeposit Initial deposit to the vault. If 0, no deposit will be made.
* @dev This function is the one stop solution to create a new vault with all necessary admin functions or auxiliery contracts.
* @dev If `rewardsData` is not empty `deployStaking` must be true
*/
function deployVault(
VaultInitParams memory vaultData,
DeploymentArgs memory adapterData,
DeploymentArgs memory strategyData,
bool deployStaking,
bytes memory rewardsData,
VaultMetadata memory metadata,
uint256 initialDeposit
) external canCreate returns (address vault) {
IDeploymentController _deploymentController = deploymentController;
_verifyToken(address(vaultData.asset));
if (
address(vaultData.adapter) != address(0) &&
(adapterData.id > 0 ||
!cloneRegistry.cloneExists(address(vaultData.adapter)))
) revert InvalidConfig();
if (adapterData.id > 0)
vaultData.adapter = IERC4626(
_deployAdapter(
vaultData.asset,
adapterData,
strategyData,
_deploymentController
)
);
vault = _deployVault(vaultData, _deploymentController);
address staking;
if (deployStaking)
staking = _deployStaking(
IERC20(address(vault)),
_deploymentController
);
_registerCreatedVault(vault, staking, metadata);
if (rewardsData.length > 0) {
if (!deployStaking) revert InvalidConfig();
_handleVaultStakingRewards(vault, rewardsData);
}
emit VaultDeployed(vault, staking, address(vaultData.adapter));
_handleInitialDeposit(
initialDeposit,
IERC20(vaultData.asset),
IERC4626(vault)
);
}
/// @notice Deploys a new vault contract using the `activeTemplateId`.
function _deployVault(
VaultInitParams memory vaultData,
IDeploymentController _deploymentController
) internal returns (address vault) {
vaultData.owner = address(adminProxy);
(, bytes memory returnData) = adminProxy.execute(
address(_deploymentController),
abi.encodeWithSelector(
DEPLOY_SIG,
VAULT,
activeTemplateId[VAULT],
abi.encodeWithSelector(IVault.initialize.selector, vaultData)
)
);
vault = abi.decode(returnData, (address));
}
/// @notice Registers newly created vault metadata.
function _registerCreatedVault(
address vault,
address staking,
VaultMetadata memory metadata
) internal {
metadata.vault = vault;
metadata.staking = staking;
metadata.creator = msg.sender;
_registerVault(vault, metadata);
}
/// @notice Prepares and calls `addStakingRewardsTokens` for the newly created staking contract.
function _handleVaultStakingRewards(
address vault,
bytes memory rewardsData
) internal {
address[] memory vaultContracts = new address[](1);
bytes[] memory rewardsDatas = new bytes[](1);
vaultContracts[0] = vault;
rewardsDatas[0] = rewardsData;
addStakingRewardsTokens(vaultContracts, rewardsDatas);
}
function _handleInitialDeposit(
uint256 initialDeposit,
IERC20 asset,
IERC4626 target
) internal {
if (initialDeposit > 0) {
asset.safeTransferFrom(msg.sender, address(this), initialDeposit);
asset.approve(address(target), initialDeposit);
target.deposit(initialDeposit, msg.sender);
}
}
/*//////////////////////////////////////////////////////////////
ADAPTER DEPLOYMENT LOGIC
//////////////////////////////////////////////////////////////*/
/**
* @notice Deploy a new Adapter with our without a strategy. Caller must be owner.
* @param asset Asset which will be used by the adapter.
* @param adapterData Encoded adapter init data.
* @param strategyData Encoded strategy init data.
*/
function deployAdapter(
IERC20 asset,
DeploymentArgs memory adapterData,
DeploymentArgs memory strategyData,
uint256 initialDeposit
) external canCreate returns (address adapter) {
_verifyToken(address(asset));
adapter = _deployAdapter(
asset,
adapterData,
strategyData,
deploymentController
);
_handleInitialDeposit(initialDeposit, asset, IERC4626(adapter));
}
/**
* @notice Deploys an adapter and optionally a strategy.
* @dev Adds the newly deployed strategy to the adapter.
*/
function _deployAdapter(
IERC20 asset,
DeploymentArgs memory adapterData,
DeploymentArgs memory strategyData,
IDeploymentController _deploymentController
) internal returns (address) {
address strategy;
bytes4[8] memory requiredSigs;
if (strategyData.id > 0) {
strategy = _deployStrategy(strategyData, _deploymentController);
requiredSigs = templateRegistry
.getTemplate(STRATEGY, strategyData.id)
.requiredSigs;
}
return
__deployAdapter(
adapterData,
abi.encode(
asset,
address(adminProxy),
IStrategy(strategy),
harvestCooldown,
requiredSigs,
strategyData.data
),
_deploymentController
);
}
/// @notice Deploys an adapter and sets the management fee via `AdminProxy`
function __deployAdapter(
DeploymentArgs memory adapterData,
bytes memory baseAdapterData,
IDeploymentController _deploymentController
) internal returns (address adapter) {
(, bytes memory returnData) = adminProxy.execute(
address(_deploymentController),
abi.encodeWithSelector(
DEPLOY_SIG,
ADAPTER,
adapterData.id,
_encodeAdapterData(adapterData, baseAdapterData)
)
);
adapter = abi.decode(returnData, (address));
adminProxy.execute(
adapter,
abi.encodeWithSelector(
IAdapter.setPerformanceFee.selector,
performanceFee
)
);
}
/// @notice Encodes adapter init call. Was moved into its own function to fix "stack too deep" error.
function _encodeAdapterData(
DeploymentArgs memory adapterData,
bytes memory baseAdapterData
) internal returns (bytes memory) {
return
abi.encodeWithSelector(
IAdapter.initialize.selector,
baseAdapterData,
templateRegistry.getTemplate(ADAPTER, adapterData.id).registry,
adapterData.data
);
}
/// @notice Deploys a new strategy contract.
function _deployStrategy(
DeploymentArgs memory strategyData,
IDeploymentController _deploymentController
) internal returns (address strategy) {
(, bytes memory returnData) = adminProxy.execute(
address(_deploymentController),
abi.encodeWithSelector(DEPLOY_SIG, STRATEGY, strategyData.id, "")
);
strategy = abi.decode(returnData, (address));
}
/*//////////////////////////////////////////////////////////////
STAKING DEPLOYMENT LOGIC
//////////////////////////////////////////////////////////////*/
/**
* @notice Deploy a new staking contract. Caller must be owner.
* @param asset The staking token for the new contract.
* @dev Deploys `MultiRewardsStaking` based on the latest templateTemplateKey.
*/
function deployStaking(IERC20 asset) external canCreate returns (address) {
_verifyToken(address(asset));
return _deployStaking(asset, deploymentController);
}
/// @notice Deploys a new staking contract using the activeTemplateId.
function _deployStaking(
IERC20 asset,
IDeploymentController _deploymentController
) internal returns (address staking) {
(, bytes memory returnData) = adminProxy.execute(
address(_deploymentController),
abi.encodeWithSelector(
DEPLOY_SIG,
STAKING,
activeTemplateId[STAKING],
abi.encodeWithSelector(
IMultiRewardStaking.initialize.selector,
asset,
escrow,
adminProxy
)
)
);
staking = abi.decode(returnData, (address));
}
/*//////////////////////////////////////////////////////////////
VAULT MANAGEMENT LOGIC
//////////////////////////////////////////////////////////////*/
error DoesntExist(address adapter);
/**
* @notice Propose a new Adapter. Caller must be creator of the vaults.
* @param vaults Vaults to propose the new adapter for.
* @param newAdapter New adapters to propose.
*/
function proposeVaultAdapters(
address[] calldata vaults,
IERC4626[] calldata newAdapter
) external {
uint8 len = uint8(vaults.length);
_verifyEqualArrayLength(len, newAdapter.length);
ICloneRegistry _cloneRegistry = cloneRegistry;
for (uint8 i = 0; i < len; i++) {
_verifyCreator(vaults[i]);
if (!_cloneRegistry.cloneExists(address(newAdapter[i])))
revert DoesntExist(address(newAdapter[i]));
adminProxy.execute(
vaults[i],
abi.encodeWithSelector(
IVault.proposeAdapter.selector,
newAdapter[i]
)
);
}
}
/**
* @notice Change adapter of a vault to the previously proposed adapter.
* @param vaults Addresses of the vaults to change
*/
function changeVaultAdapters(address[] calldata vaults) external {
uint8 len = uint8(vaults.length);
for (uint8 i = 0; i < len; i++) {
adminProxy.execute(
vaults[i],
abi.encodeWithSelector(IVault.changeAdapter.selector)
);
}
}
/**
* @notice Sets new fees per vault. Caller must be creator of the vaults.
* @param vaults Addresses of the vaults to change
* @param fees New fee structures for these vaults
* @dev Value is in 1e18, e.g. 100% = 1e18 - 1 BPS = 1e12
*/
function proposeVaultFees(
address[] calldata vaults,
VaultFees[] calldata fees
) external {
uint8 len = uint8(vaults.length);
_verifyEqualArrayLength(len, fees.length);
for (uint8 i = 0; i < len; i++) {
_verifyCreator(vaults[i]);
adminProxy.execute(
vaults[i],
abi.encodeWithSelector(IVault.proposeFees.selector, fees[i])
);
}
}
/**
* @notice Change adapter of a vault to the previously proposed adapter.
* @param vaults Addresses of the vaults
*/
function changeVaultFees(address[] calldata vaults) external {
uint8 len = uint8(vaults.length);
for (uint8 i = 0; i < len; i++) {
adminProxy.execute(
vaults[i],
abi.encodeWithSelector(IVault.changeFees.selector)
);
}
}
/**
* @notice Sets new Quit Periods for Vaults. Caller must be creator of the vaults.
* @param vaults Addresses of the vaults to change
* @param quitPeriods QuitPeriod in seconds
* @dev Minimum value is 1 day max is 7 days.
* @dev Cant be called if recently a new fee or adapter has been proposed
*/
function setVaultQuitPeriods(
address[] calldata vaults,
uint256[] calldata quitPeriods
) external {
uint8 len = uint8(vaults.length);
_verifyEqualArrayLength(len, quitPeriods.length);
for (uint8 i = 0; i < len; i++) {
_verifyCreator(vaults[i]);
adminProxy.execute(
vaults[i],
abi.encodeWithSelector(
IVault.setQuitPeriod.selector,
quitPeriods[i]
)
);
}
}
/**
* @notice Sets new Fee Recipients for Vaults. Caller must be creator of the vaults.
* @param vaults Addresses of the vaults to change
* @param feeRecipients fee recipient for this vault
* @dev address must not be 0
*/
function setVaultFeeRecipients(
address[] calldata vaults,
address[] calldata feeRecipients
) external {
uint8 len = uint8(vaults.length);
_verifyEqualArrayLength(len, feeRecipients.length);
for (uint8 i = 0; i < len; i++) {
_verifyCreator(vaults[i]);
adminProxy.execute(
vaults[i],
abi.encodeWithSelector(
IVault.setFeeRecipient.selector,
feeRecipients[i]
)
);
}
}
/**
* @notice Sets new DepositLimit for Vaults. Caller must be creator of the vaults.
* @param vaults Addresses of the vaults to change
* @param depositLimits Maximum amount of assets that can be deposited.
*/
function setVaultDepositLimits(
address[] calldata vaults,
uint256[] calldata depositLimits
) external {
uint8 len = uint8(vaults.length);
_verifyEqualArrayLength(len, depositLimits.length);
for (uint8 i = 0; i < len; i++) {
_verifyCreator(vaults[i]);
adminProxy.execute(
vaults[i],
abi.encodeWithSelector(
IVault.setDepositLimit.selector,
depositLimits[i]
)
);
}
}
/*//////////////////////////////////////////////////////////////
REGISTER VAULT
//////////////////////////////////////////////////////////////*/
IVaultRegistry public vaultRegistry;
/// @notice Call the `VaultRegistry` to register a vault via `AdminProxy`
function _registerVault(
address vault,
VaultMetadata memory metadata
) internal {
adminProxy.execute(
address(vaultRegistry),
abi.encodeWithSelector(
IVaultRegistry.registerVault.selector,
metadata
)
);
}
/*//////////////////////////////////////////////////////////////
ENDORSEMENT / REJECTION LOGIC
//////////////////////////////////////////////////////////////*/
/**
* @notice Set permissions for an array of target. Caller must be owner.
* @param targets `AdminProxy`
* @param newPermissions An array of permissions to set for the targets.
* @dev See `PermissionRegistry` for more details
*/
function setPermissions(
address[] calldata targets,
Permission[] calldata newPermissions
) external onlyOwner {
// No need to check matching array length since its already done in the permissionRegistry
adminProxy.execute(
address(permissionRegistry),
abi.encodeWithSelector(
IPermissionRegistry.setPermissions.selector,
targets,
newPermissions
)
);
}
/*//////////////////////////////////////////////////////////////
STAKING MANAGEMENT LOGIC
//////////////////////////////////////////////////////////////*/
/**
* @notice Adds a new rewardToken which can be earned via staking. Caller must be creator of the Vault or owner.
* @param vaults Vaults of which the staking contracts should be targeted
* @param rewardTokenData Token that can be earned by staking.
* @dev `rewardToken` - Token that can be earned by staking.
* @dev `rewardsPerSecond` - The rate in which `rewardToken` will be accrued.
* @dev `amount` - Initial funding amount for this reward.
* @dev `useEscrow Bool` - if the rewards should be escrowed on claim.
* @dev `escrowPercentage` - The percentage of the reward that gets escrowed in 1e18. (1e18 = 100%, 1e14 = 1 BPS)
* @dev `escrowDuration` - The duration of the escrow.
* @dev `offset` - A cliff after claim before the escrow starts.
* @dev See `MultiRewardsStaking` for more details.
*/
function addStakingRewardsTokens(
address[] memory vaults,
bytes[] memory rewardTokenData
) public {
_verifyEqualArrayLength(vaults.length, rewardTokenData.length);
address staking;
uint8 len = uint8(vaults.length);
for (uint256 i = 0; i < len; i++) {
(
address rewardsToken,
uint160 rewardsPerSecond,
uint256 amount,
bool useEscrow,
uint224 escrowDuration,
uint24 escrowPercentage,
uint256 offset
) = abi.decode(
rewardTokenData[i],
(address, uint160, uint256, bool, uint224, uint24, uint256)
);
_verifyToken(rewardsToken);
staking = _verifyCreatorOrOwner(vaults[i]).staking;
adminProxy.execute(
rewardsToken,
abi.encodeWithSelector(
IERC20.approve.selector,
staking,
type(uint256).max
)
);
IERC20(rewardsToken).approve(staking, type(uint256).max);
IERC20(rewardsToken).transferFrom(
msg.sender,
address(adminProxy),
amount
);
adminProxy.execute(
staking,
abi.encodeWithSelector(
IMultiRewardStaking.addRewardToken.selector,
rewardsToken,
rewardsPerSecond,
amount,
useEscrow,
escrowDuration,
escrowPercentage,
offset
)
);
}
}
/**
* @notice Changes rewards speed for a rewardToken. This works only for rewards that accrue over time. Caller must be creator of the Vault.
* @param vaults Vaults of which the staking contracts should be targeted
* @param rewardTokens Token that can be earned by staking.
* @param rewardsSpeeds The rate in which `rewardToken` will be accrued.
* @dev See `MultiRewardsStaking` for more details.
*/
function changeStakingRewardsSpeeds(
address[] calldata vaults,
IERC20[] calldata rewardTokens,
uint160[] calldata rewardsSpeeds
) external {
uint8 len = uint8(vaults.length);
_verifyEqualArrayLength(len, rewardTokens.length);
_verifyEqualArrayLength(len, rewardsSpeeds.length);
address staking;
for (uint256 i = 0; i < len; i++) {
staking = _verifyCreator(vaults[i]).staking;
adminProxy.execute(
staking,
abi.encodeWithSelector(
IMultiRewardStaking.changeRewardSpeed.selector,
rewardTokens[i],
rewardsSpeeds[i]
)
);
}
}
/**
* @notice Funds rewards for a rewardToken.
* @param vaults Vaults of which the staking contracts should be targeted
* @param rewardTokens Token that can be earned by staking.
* @param amounts The amount of rewardToken that will fund this reward.
* @dev See `MultiRewardStaking` for more details.
*/
function fundStakingRewards(
address[] calldata vaults,
IERC20[] calldata rewardTokens,
uint256[] calldata amounts
) external {
uint8 len = uint8(vaults.length);
_verifyEqualArrayLength(len, rewardTokens.length);
_verifyEqualArrayLength(len, amounts.length);
address staking;
for (uint256 i = 0; i < len; i++) {
staking = vaultRegistry.getVault(vaults[i]).staking;
rewardTokens[i].transferFrom(msg.sender, address(this), amounts[i]);
IMultiRewardStaking(staking).fundReward(
rewardTokens[i],
amounts[i]
);
}
}
/*//////////////////////////////////////////////////////////////
ESCROW MANAGEMENT LOGIC
//////////////////////////////////////////////////////////////*/
IMultiRewardEscrow public escrow;
/**
* @notice Set fees for multiple tokens. Caller must be the owner.
* @param tokens Array of tokens.
* @param fees Array of fees for `tokens` in 1e18. (1e18 = 100%, 1e14 = 1 BPS)
* @dev See `MultiRewardEscrow` for more details.
* @dev We dont need to verify array length here since its done already in `MultiRewardEscrow`
*/
function setEscrowTokenFees(
IERC20[] calldata tokens,
uint256[] calldata fees
) external onlyOwner {
adminProxy.execute(
address(escrow),
abi.encodeWithSelector(
IMultiRewardEscrow.setFees.selector,
tokens,
fees
)
);
}
/*//////////////////////////////////////////////////////////////
TEMPLATE LOGIC
//////////////////////////////////////////////////////////////*/
/**
* @notice Adds a new templateCategory to the registry. Caller must be owner.
* @param templateCategories A new category of templates.
* @dev See `TemplateRegistry` for more details.
*/
function addTemplateCategories(
bytes32[] calldata templateCategories
) external onlyOwner {
address _deploymentController = address(deploymentController);
uint8 len = uint8(templateCategories.length);
for (uint256 i = 0; i < len; i++) {
adminProxy.execute(
_deploymentController,
abi.encodeWithSelector(
IDeploymentController.addTemplateCategory.selector,
templateCategories[i]
)
);
}
}
/**
* @notice Toggles the endorsement of a templates. Caller must be owner.
* @param templateCategories TemplateCategory of the template to endorse.
* @param templateIds TemplateId of the template to endorse.
* @dev See `TemplateRegistry` for more details.
*/
function toggleTemplateEndorsements(
bytes32[] calldata templateCategories,
bytes32[] calldata templateIds
) external onlyOwner {
uint8 len = uint8(templateCategories.length);
_verifyEqualArrayLength(len, templateIds.length);
address _deploymentController = address(deploymentController);
for (uint256 i = 0; i < len; i++) {
adminProxy.execute(
address(_deploymentController),
abi.encodeWithSelector(
ITemplateRegistry.toggleTemplateEndorsement.selector,
templateCategories[i],
templateIds[i]
)
);
}
}
/*//////////////////////////////////////////////////////////////
PAUSING LOGIC
//////////////////////////////////////////////////////////////*/
/// @notice Pause Deposits and withdraw all funds from the underlying protocol. Caller must be owner.
function pauseAdapters(address[] calldata vaults) external onlyOwner {
uint8 len = uint8(vaults.length);
for (uint256 i = 0; i < len; i++) {
adminProxy.execute(
IVault(vaults[i]).adapter(),
abi.encodeWithSelector(IPausable.pause.selector)
);
}
}
/// @notice Unpause Deposits and deposit all funds into the underlying protocol. Caller must be owner.
function unpauseAdapters(address[] calldata vaults) external onlyOwner {
uint8 len = uint8(vaults.length);
for (uint256 i = 0; i < len; i++) {
adminProxy.execute(
IVault(vaults[i]).adapter(),
abi.encodeWithSelector(IPausable.unpause.selector)
);
}
}
/// @notice Pause deposits. Caller must be owner or creator of the Vault.
function pauseVaults(address[] calldata vaults) external {
uint8 len = uint8(vaults.length);
for (uint256 i = 0; i < len; i++) {
_verifyCreator(vaults[i]);
adminProxy.execute(
vaults[i],
abi.encodeWithSelector(IPausable.pause.selector)
);
}
}
/// @notice Unpause deposits. Caller must be owner or creator of the Vault.
function unpauseVaults(address[] calldata vaults) external {
uint8 len = uint8(vaults.length);
for (uint256 i = 0; i < len; i++) {
_verifyCreator(vaults[i]);
adminProxy.execute(
vaults[i],
abi.encodeWithSelector(IPausable.unpause.selector)
);
}
}
/*//////////////////////////////////////////////////////////////
VERIFICATION LOGIC
//////////////////////////////////////////////////////////////*/
error NotSubmitterNorOwner(address caller);
error NotSubmitter(address caller);
error NotAllowed(address subject);
error ArrayLengthMismatch();
/// @notice Verify that the caller is the creator of the vault or owner of `VaultController` (admin rights).
function _verifyCreatorOrOwner(
address vault
) internal returns (VaultMetadata memory metadata) {
metadata = vaultRegistry.getVault(vault);
if (msg.sender != metadata.creator && msg.sender != owner)
revert NotSubmitterNorOwner(msg.sender);
}
/// @notice Verify that the caller is the creator of the vault.
function _verifyCreator(
address vault
) internal view returns (VaultMetadata memory metadata) {
metadata = vaultRegistry.getVault(vault);
if (msg.sender != metadata.creator) revert NotSubmitter(msg.sender);
}
/// @notice Verify that the token is not rejected nor a clone.
function _verifyToken(address token) internal view {
if (
(
permissionRegistry.endorsed(address(0))
? !permissionRegistry.endorsed(token)
: permissionRegistry.rejected(token)
) ||
cloneRegistry.cloneExists(token) ||
token == address(0)
) revert NotAllowed(token);
}
/// @notice Verify that the array lengths are equal.
function _verifyEqualArrayLength(
uint256 length1,
uint256 length2
) internal pure {
if (length1 != length2) revert ArrayLengthMismatch();
}
modifier canCreate() {
if (
permissionRegistry.endorsed(address(1))
? !permissionRegistry.endorsed(msg.sender)
: permissionRegistry.rejected(msg.sender)
) revert NotAllowed(msg.sender);
_;
}
/*//////////////////////////////////////////////////////////////
OWNERSHIP LOGIC
//////////////////////////////////////////////////////////////*/
IAdminProxy public adminProxy;
/**
* @notice Nominates a new owner of `AdminProxy`. Caller must be owner.
* @dev Must be called if the `VaultController` gets swapped out or upgraded
*/
function nominateNewAdminProxyOwner(address newOwner) external onlyOwner {
adminProxy.nominateNewOwner(newOwner);
}
/**
* @notice Accepts ownership of `AdminProxy`. Caller must be nominated owner.
* @dev Must be called after construction
*/
function acceptAdminProxyOwnership() external {
adminProxy.acceptOwnership();
}
/*//////////////////////////////////////////////////////////////
MANAGEMENT FEE LOGIC
//////////////////////////////////////////////////////////////*/
uint256 public performanceFee;
event PerformanceFeeChanged(uint256 oldFee, uint256 newFee);
error InvalidPerformanceFee(uint256 fee);
/**
* @notice Set a new performanceFee for all new adapters. Caller must be owner.
* @param newFee performance fee in 1e18.
* @dev Fees can be 0 but never more than 2e17 (1e18 = 100%, 1e14 = 1 BPS)
* @dev Can be retroactively applied to existing adapters.
*/
function setPerformanceFee(uint256 newFee) external onlyOwner {
// Dont take more than 20% performanceFee
if (newFee > 2e17) revert InvalidPerformanceFee(newFee);
emit PerformanceFeeChanged(performanceFee, newFee);
performanceFee = newFee;
}
/**
* @notice Set a new performanceFee for existing adapters. Caller must be owner.
* @param adapters array of adapters to set the management fee for.
*/
function setAdapterPerformanceFees(
address[] calldata adapters
) external onlyOwner {
uint8 len = uint8(adapters.length);
for (uint256 i = 0; i < len; i++) {
adminProxy.execute(
adapters[i],
abi.encodeWithSelector(
IAdapter.setPerformanceFee.selector,
performanceFee
)
);
}
}
/*//////////////////////////////////////////////////////////////
HARVEST COOLDOWN LOGIC
//////////////////////////////////////////////////////////////*/
uint256 public harvestCooldown;
event HarvestCooldownChanged(uint256 oldCooldown, uint256 newCooldown);
error InvalidHarvestCooldown(uint256 cooldown);
/**
* @notice Set a new harvestCooldown for all new adapters. Caller must be owner.
* @param newCooldown Time in seconds that must pass before a harvest can be called again.
* @dev Cant be longer than 1 day.
* @dev Can be retroactively applied to existing adapters.
*/
function setHarvestCooldown(uint256 newCooldown) external onlyOwner {
// Dont wait more than X seconds
if (newCooldown > 1 days) revert InvalidHarvestCooldown(newCooldown);
emit HarvestCooldownChanged(harvestCooldown, newCooldown);
harvestCooldown = newCooldown;
}
/**
* @notice Set a new harvestCooldown for existing adapters. Caller must be owner.
* @param adapters Array of adapters to set the cooldown for.
*/
function setAdapterHarvestCooldowns(
address[] calldata adapters
) external onlyOwner {
uint8 len = uint8(adapters.length);
for (uint256 i = 0; i < len; i++) {
adminProxy.execute(
adapters[i],
abi.encodeWithSelector(
IAdapter.setHarvestCooldown.selector,
harvestCooldown
)
);
}
}
/*//////////////////////////////////////////////////////////////
DEPLYOMENT CONTROLLER LOGIC
//////////////////////////////////////////////////////////////*/
IDeploymentController public deploymentController;
ICloneRegistry public cloneRegistry;
ITemplateRegistry public templateRegistry;
IPermissionRegistry public permissionRegistry;
event DeploymentControllerChanged(
address oldController,
address newController
);
error InvalidDeploymentController(address deploymentController);
/**
* @notice Sets a new `DeploymentController` and saves its auxilary contracts. Caller must be owner.
* @param _deploymentController New DeploymentController.
*/
function setDeploymentController(
IDeploymentController _deploymentController
) external onlyOwner {
_setDeploymentController(_deploymentController);
}
function _setDeploymentController(
IDeploymentController _deploymentController
) internal {
if (
address(_deploymentController) == address(0) ||
address(deploymentController) == address(_deploymentController)
) revert InvalidDeploymentController(address(_deploymentController));
emit DeploymentControllerChanged(
address(deploymentController),
address(_deploymentController)
);
// Dont try to change ownership on construction
if (address(deploymentController) != address(0))
_transferDependencyOwnership(address(_deploymentController));
deploymentController = _deploymentController;
cloneRegistry = _deploymentController.cloneRegistry();
templateRegistry = _deploymentController.templateRegistry();
}
function _transferDependencyOwnership(
address _deploymentController
) internal {
adminProxy.execute(
address(deploymentController),
abi.encodeWithSelector(
IDeploymentController.nominateNewDependencyOwner.selector,
_deploymentController
)
);
adminProxy.execute(
_deploymentController,
abi.encodeWithSelector(
IDeploymentController.acceptDependencyOwnership.selector,
""
)
);
}
/*//////////////////////////////////////////////////////////////
TEMPLATE KEY LOGIC
//////////////////////////////////////////////////////////////*/
mapping(bytes32 => bytes32) public activeTemplateId;
event ActiveTemplateIdChanged(bytes32 oldKey, bytes32 newKey);
error SameKey(bytes32 templateKey);
/**
* @notice Set a templateId which shall be used for deploying certain contracts. Caller must be owner.
* @param templateCategory TemplateCategory to set an active key for.
* @param templateId TemplateId that should be used when creating a new contract of `templateCategory`
* @dev Currently `Vault` and `Staking` use a template set via `activeTemplateId`.
* @dev If this contract should deploy Vaults of a second generation this can be set via the `activeTemplateId`.
*/
function setActiveTemplateId(
bytes32 templateCategory,
bytes32 templateId
) external onlyOwner {
bytes32 oldTemplateId = activeTemplateId[templateCategory];
if (oldTemplateId == templateId) revert SameKey(templateId);
emit ActiveTemplateIdChanged(oldTemplateId, templateId);
activeTemplateId[templateCategory] = templateId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (interfaces/IERC4626.sol)
pragma solidity ^0.8.0;
import "../token/ERC20/IERC20Upgradeable.sol";
import "../token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
/**
* @dev Interface of the ERC4626 "Tokenized Vault Standard", as defined in
* https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].
*
* _Available since v4.7._
*/
interface IERC4626Upgradeable is IERC20Upgradeable, IERC20MetadataUpgradeable {
event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed sender,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
/**
* @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
*
* - MUST be an ERC-20 token contract.
* - MUST NOT revert.
*/
function asset() external view returns (address assetTokenAddress);
/**
* @dev Returns the total amount of the underlying asset that is “managed” by Vault.
*
* - SHOULD include any compounding that occurs from yield.
* - MUST be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT revert.
*/
function totalAssets() external view returns (uint256 totalManagedAssets);
/**
* @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToShares(uint256 assets) external view returns (uint256 shares);
/**
* @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToAssets(uint256 shares) external view returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
* through a deposit call.
*
* - MUST return a limited value if receiver is subject to some deposit limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
* - MUST NOT revert.
*/
function maxDeposit(address receiver) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
* call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
* in the same transaction.
* - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
* deposit would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewDeposit(uint256 assets) external view returns (uint256 shares);
/**
* @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* deposit execution, and are accounted for during deposit.
* - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
* - MUST return a limited value if receiver is subject to some mint limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
* - MUST NOT revert.
*/
function maxMint(address receiver) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
* in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
* same transaction.
* - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
* would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by minting.
*/
function previewMint(uint256 shares) external view returns (uint256 assets);
/**
* @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
* execution, and are accounted for during mint.
* - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function mint(uint256 shares, address receiver) external returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
* Vault, through a withdraw call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxWithdraw(address owner) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
* call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
* called
* in the same transaction.
* - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
* the withdrawal would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewWithdraw(uint256 assets) external view returns (uint256 shares);
/**
* @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* withdraw execution, and are accounted for during withdraw.
* - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function withdraw(
uint256 assets,
address receiver,
address owner
) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
* through a redeem call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxRedeem(address owner) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
* in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
* same transaction.
* - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
* redemption would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by redeeming.
*/
function previewRedeem(uint256 shares) external view returns (uint256 assets);
/**
* @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* redeem execution, and are accounted for during redeem.
* - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function redeem(
uint256 shares,
address receiver,
address owner
) external returns (uint256 assets);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.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 v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20Upgradeable.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20MetadataUpgradeable is IERC20Upgradeable {
/**
* @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 v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface 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.8.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20Upgradeable.sol";
import "../extensions/draft-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;
function safeTransfer(
IERC20Upgradeable token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
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));
}
function safeIncreaseAllowance(
IERC20Upgradeable token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20Upgradeable token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
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");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (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
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev 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: GPL-3.0
// Docgen-SOLC: 0.8.15
pragma solidity ^0.8.15;
import { IERC20Upgradeable as IERC20 } from "openzeppelin-contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
struct Escrow {
/// @notice The escrowed token
IERC20 token;
/// @notice Timestamp of the start of the unlock
uint32 start;
/// @notice The timestamp the unlock ends at
uint32 end;
/// @notice The timestamp the index was last updated at
uint32 lastUpdateTime;
/// @notice Initial balance of the escrow
uint256 initialBalance;
/// @notice Current balance of the escrow
uint256 balance;
/// @notice Owner of the escrow
address account;
}
struct Fee {
/// @notice Accrued fee amount
uint256 accrued;
/// @notice Fee percentage in 1e18 for 100% (1 BPS = 1e14)
uint256 feePerc;
}
interface IMultiRewardEscrow {
function lock(
IERC20 token,
address account,
uint256 amount,
uint32 duration,
uint32 offset
) external;
function setFees(IERC20[] memory tokens, uint256[] memory tokenFees) external;
function fees(IERC20 token) external view returns (Fee memory);
}// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.15
pragma solidity ^0.8.15;
import { IERC4626Upgradeable as IERC4626, IERC20Upgradeable as IERC20 } from "openzeppelin-contracts-upgradeable/interfaces/IERC4626Upgradeable.sol";
import { IOwned } from "./IOwned.sol";
import { IPermit } from "./IPermit.sol";
import { IPausable } from "./IPausable.sol";
import { IMultiRewardEscrow } from "./IMultiRewardEscrow.sol";
/// @notice The whole reward and accrual logic is heavily based on the Fei Protocol's Flywheel contracts.
/// https://github.com/fei-protocol/flywheel-v2/blob/main/src/rewards/FlywheelStaticRewards.sol
/// https://github.com/fei-protocol/flywheel-v2/blob/main/src/FlywheelCore.sol
struct RewardInfo {
/// @notice scalar for the rewardToken
uint64 ONE;
/// @notice Rewards per second
uint160 rewardsPerSecond;
/// @notice The timestamp the rewards end at
/// @dev use 0 to specify no end
uint32 rewardsEndTimestamp;
/// @notice The strategy's last updated index
uint224 index;
/// @notice The timestamp the index was last updated at
uint32 lastUpdatedTimestamp;
}
struct EscrowInfo {
/// @notice Percentage of reward that gets escrowed in 1e18 (1e18 = 100%, 1e14 = 1 BPS)
uint192 escrowPercentage;
/// @notice Duration of the escrow in seconds
uint32 escrowDuration;
/// @notice A cliff before the escrow starts in seconds
uint32 offset;
}
interface IMultiRewardStaking is IERC4626, IOwned, IPermit, IPausable {
function addRewardToken(
IERC20 rewardToken,
uint160 rewardsPerSecond,
uint256 amount,
bool useEscrow,
uint192 escrowPercentage,
uint32 escrowDuration,
uint32 offset
) external;
function changeRewardSpeed(IERC20 rewardToken, uint160 rewardsPerSecond) external;
function fundReward(IERC20 rewardToken, uint256 amount) external;
function initialize(
IERC20 _stakingToken,
IMultiRewardEscrow _escrow,
address _owner
) external;
function rewardInfos(IERC20 rewardToken) external view returns (RewardInfo memory);
function escrowInfos(IERC20 rewardToken) external view returns (EscrowInfo memory);
}// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.15
pragma solidity ^0.8.15;
interface IOwned {
function owner() external view returns (address);
function nominatedOwner() external view returns (address);
function nominateNewOwner(address owner) external;
function acceptOwnership() external;
}// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.15
pragma solidity ^0.8.15;
interface IPausable {
function paused() external view returns (bool);
function pause() external;
function unpause() external;
}// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.15
pragma solidity ^0.8.15;
interface IPermit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function DOMAIN_SEPARATOR() external view returns (bytes32);
function nonces(address caller) external view returns (uint256);
}// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.15
pragma solidity ^0.8.15;
import {IOwned} from "../IOwned.sol";
import {IERC4626Upgradeable as IERC4626} from "openzeppelin-contracts-upgradeable/interfaces/IERC4626Upgradeable.sol";
import {IPermit} from "../IPermit.sol";
import {IPausable} from "../IPausable.sol";
interface IAdapter is IERC4626, IOwned, IPermit, IPausable {
function strategy() external view returns (address);
function strategyConfig() external view returns (bytes memory);
function strategyDeposit(uint256 assets, uint256 shares) external;
function strategyWithdraw(uint256 assets, uint256 shares) external;
function supportsInterface(bytes4 interfaceId) external view returns (bool);
function setPerformanceFee(uint256 fee) external;
function performanceFee() external view returns (uint256);
function highWaterMark() external view returns (uint256);
function accruedPerformanceFee() external view returns (uint256);
function harvest() external;
function lastHarvest() external view returns (uint256);
function harvestCooldown() external view returns (uint256);
function setHarvestCooldown(uint256 harvestCooldown) external;
function initialize(
bytes memory adapterBaseData,
address externalRegistry,
bytes memory adapterData
) external;
function decimals() external view returns (uint8);
function decimalOffset() external view returns (uint8);
}// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.15
pragma solidity ^0.8.15;
import { IOwned } from "../IOwned.sol";
interface IAdminProxy is IOwned {
function execute(address target, bytes memory callData) external returns (bool, bytes memory);
}// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.15
pragma solidity ^0.8.15;
import { IOwned } from "../IOwned.sol";
import { Template } from "./ITemplateRegistry.sol";
interface ICloneFactory is IOwned {
function deploy(Template memory template, bytes memory data) external returns (address);
}// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.15
pragma solidity ^0.8.15;
import { IOwned } from "../IOwned.sol";
interface ICloneRegistry is IOwned {
function cloneExists(address clone) external view returns (bool);
function addClone(
bytes32 templateCategory,
bytes32 templateId,
address clone
) external;
}// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.15
pragma solidity ^0.8.15;
import { ICloneFactory } from "./ICloneFactory.sol";
import { ICloneRegistry } from "./ICloneRegistry.sol";
import { IPermissionRegistry } from "./IPermissionRegistry.sol";
import { ITemplateRegistry, Template } from "./ITemplateRegistry.sol";
interface IDeploymentController is ICloneFactory, ICloneRegistry {
function templateCategoryExists(bytes32 templateCategory) external view returns (bool);
function templateExists(bytes32 templateId) external view returns (bool);
function addTemplate(
bytes32 templateCategory,
bytes32 templateId,
Template memory template
) external;
function addTemplateCategory(bytes32 templateCategory) external;
function toggleTemplateEndorsement(bytes32 templateCategory, bytes32 templateId) external;
function getTemplate(bytes32 templateCategory, bytes32 templateId) external view returns (Template memory);
function nominateNewDependencyOwner(address _owner) external;
function acceptDependencyOwnership() external;
function cloneFactory() external view returns (ICloneFactory);
function cloneRegistry() external view returns (ICloneRegistry);
function templateRegistry() external view returns (ITemplateRegistry);
function PermissionRegistry() external view returns (IPermissionRegistry);
function addClone(address clone) external;
}// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.15
pragma solidity ^0.8.15;
import { IOwned } from "../IOwned.sol";
struct Permission {
bool endorsed;
bool rejected;
}
interface IPermissionRegistry is IOwned {
function setPermissions(address[] calldata targets, Permission[] calldata newPermissions) external;
function endorsed(address target) external view returns (bool);
function rejected(address target) external view returns (bool);
}// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.15
pragma solidity ^0.8.15;
interface IStrategy {
function harvest() external;
function verifyAdapterSelectorCompatibility(bytes4[8] memory sigs) external;
function verifyAdapterCompatibility(bytes memory data) external;
function setUp(bytes memory data) external;
}// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.15
pragma solidity ^0.8.15;
import { IOwned } from "../IOwned.sol";
/// @notice Template used for creating new clones
struct Template {
/// @Notice Cloneable implementation address
address implementation;
/// @Notice implementations can only be cloned if endorsed
bool endorsed;
/// @Notice Optional - Metadata CID which can be used by the frontend to add informations to a vault/adapter...
string metadataCid;
/// @Notice If true, the implementation will require an init data to be passed to the clone function
bool requiresInitData;
/// @Notice Optional - Address of an registry which can be used in an adapter initialization
address registry;
/// @Notice Optional - Only used by Strategies. EIP-165 Signatures of an adapter required by a strategy
bytes4[8] requiredSigs;
}
interface ITemplateRegistry is IOwned {
function templates(bytes32 templateCategory, bytes32 templateId) external view returns (Template memory);
function templateCategoryExists(bytes32 templateCategory) external view returns (bool);
function templateExists(bytes32 templateId) external view returns (bool);
function getTemplateCategories() external view returns (bytes32[] memory);
function getTemplate(bytes32 templateCategory, bytes32 templateId) external view returns (Template memory);
function getTemplateIds(bytes32 templateCategory) external view returns (bytes32[] memory);
function addTemplate(
bytes32 templateType,
bytes32 templateId,
Template memory template
) external;
function addTemplateCategory(bytes32 templateCategory) external;
function toggleTemplateEndorsement(bytes32 templateCategory, bytes32 templateId) external;
}// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.15
pragma solidity ^0.8.15;
import { IERC4626Upgradeable as IERC4626, IERC20Upgradeable as IERC20 } from "openzeppelin-contracts-upgradeable/interfaces/IERC4626Upgradeable.sol";
// Fees are set in 1e18 for 100% (1 BPS = 1e14)
struct VaultFees {
uint64 deposit;
uint64 withdrawal;
uint64 management;
uint64 performance;
}
/// @notice Init data for a Vault
struct VaultInitParams {
/// @Notice Address of the deposit asset
IERC20 asset;
/// @Notice Address of the adapter used by the vault
IERC4626 adapter;
/// @Notice Fees used by the vault
VaultFees fees;
/// @Notice Address of the recipient of the fees
address feeRecipient;
/// @Notice Maximum amount of assets that can be deposited
uint256 depositLimit;
/// @Notice Owner of the vault (Usually the submitter)
address owner;
}
interface IVault is IERC4626 {
// FEE VIEWS
function accruedManagementFee() external view returns (uint256);
function accruedPerformanceFee() external view returns (uint256);
function highWaterMark() external view returns (uint256);
function assetsCheckpoint() external view returns (uint256);
function feesUpdatedAt() external view returns (uint256);
function feeRecipient() external view returns (address);
// USER INTERACTIONS
function deposit(uint256 assets) external returns (uint256);
function mint(uint256 shares) external returns (uint256);
function withdraw(uint256 assets) external returns (uint256);
function redeem(uint256 shares) external returns (uint256);
function takeManagementAndPerformanceFees() external;
// MANAGEMENT FUNCTIONS - STRATEGY
function adapter() external view returns (address);
function proposedAdapter() external view returns (address);
function proposedAdapterTime() external view returns (uint256);
function proposeAdapter(IERC4626 newAdapter) external;
function changeAdapter() external;
// MANAGEMENT FUNCTIONS - FEES
function fees() external view returns (VaultFees memory);
function proposedFees() external view returns (VaultFees memory);
function proposedFeeTime() external view returns (uint256);
function proposeFees(VaultFees memory) external;
function changeFees() external;
function setFeeRecipient(address feeRecipient) external;
// MANAGEMENT FUNCTIONS - OTHER
function quitPeriod() external view returns (uint256);
function setQuitPeriod(uint256 _quitPeriod) external;
function depositLimit() external view returns (uint256);
function setDepositLimit(uint256 _depositLimit) external;
// INITIALIZE
function initialize(
IERC20 asset_,
IERC4626 adapter_,
VaultFees memory fees_,
address feeRecipient_,
uint256 depositLimit_,
address owner
) external;
}// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.15
pragma solidity ^0.8.15;
import { VaultInitParams, VaultFees, IERC4626, IERC20 } from "./IVault.sol";
import { VaultMetadata } from "./IVaultRegistry.sol";
import { IDeploymentController } from "./IDeploymentController.sol";
struct DeploymentArgs {
/// @Notice templateId
bytes32 id;
/// @Notice encoded init params
bytes data;
}
interface IVaultController {
function deployVault(
VaultInitParams memory vaultData,
DeploymentArgs memory adapterData,
DeploymentArgs memory strategyData,
bool deployStaking,
bytes memory rewardsData,
VaultMetadata memory metadata,
uint256 initialDeposit
) external returns (address);
function deployAdapter(
IERC20 asset,
DeploymentArgs memory adapterData,
DeploymentArgs memory strategyData,
uint256 initialDeposit
) external returns (address);
function deployStaking(IERC20 asset) external returns (address);
function proposeVaultAdapters(address[] calldata vaults, IERC4626[] calldata newAdapter) external;
function changeVaultAdapters(address[] calldata vaults) external;
function proposeVaultFees(address[] calldata vaults, VaultFees[] calldata newFees) external;
function changeVaultFees(address[] calldata vaults) external;
function setVaultQuitPeriods(address[] calldata vaults, uint256[] calldata quitPeriods) external;
function setVaultFeeRecipients(address[] calldata vaults, address[] calldata feeRecipients) external;
function registerVaults(address[] calldata vaults, VaultMetadata[] calldata metadata) external;
function addClones(address[] calldata clones) external;
function toggleEndorsements(address[] calldata targets) external;
function toggleRejections(address[] calldata targets) external;
function addStakingRewardsTokens(address[] calldata vaults, bytes[] calldata rewardsTokenData) external;
function changeStakingRewardsSpeeds(
address[] calldata vaults,
IERC20[] calldata rewardTokens,
uint160[] calldata rewardsSpeeds
) external;
function fundStakingRewards(
address[] calldata vaults,
IERC20[] calldata rewardTokens,
uint256[] calldata amounts
) external;
function setEscrowTokenFees(IERC20[] calldata tokens, uint256[] calldata fees) external;
function addTemplateCategories(bytes32[] calldata templateCategories) external;
function toggleTemplateEndorsements(bytes32[] calldata templateCategories, bytes32[] calldata templateIds) external;
function pauseAdapters(address[] calldata vaults) external;
function pauseVaults(address[] calldata vaults) external;
function unpauseAdapters(address[] calldata vaults) external;
function unpauseVaults(address[] calldata vaults) external;
function nominateNewAdminProxyOwner(address newOwner) external;
function acceptAdminProxyOwnership() external;
function setPerformanceFee(uint256 newFee) external;
function setAdapterPerformanceFees(address[] calldata adapters) external;
function performanceFee() external view returns (uint256);
function setHarvestCooldown(uint256 newCooldown) external;
function setAdapterHarvestCooldowns(address[] calldata adapters) external;
function harvestCooldown() external view returns (uint256);
function setDeploymentController(IDeploymentController _deploymentController) external;
function setActiveTemplateId(bytes32 templateCategory, bytes32 templateId) external;
function activeTemplateId(bytes32 templateCategory) external view returns (bytes32);
}// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.15
pragma solidity ^0.8.15;
import { IOwned } from "../IOwned.sol";
struct VaultMetadata {
/// @notice Vault address
address vault;
/// @notice Staking contract for the vault
address staking;
/// @notice Owner and Vault creator
address creator;
/// @notice IPFS CID of vault metadata
string metadataCID;
/// @notice OPTIONAL - If the asset is an Lp Token these are its underlying assets
address[8] swapTokenAddresses;
/// @notice OPTIONAL - If the asset is an Lp Token its the pool address
address swapAddress;
/// @notice OPTIONAL - If the asset is an Lp Token this is the identifier of the exchange (1 = curve)
uint256 exchange;
}
interface IVaultRegistry is IOwned {
function getVault(address vault) external view returns (VaultMetadata memory);
function getSubmitter(address vault) external view returns (address);
function registerVault(VaultMetadata memory metadata) external;
}// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.15
pragma solidity ^0.8.15;
// https://docs.synthetix.io/contracts/source/contracts/owned
contract Owned {
address public owner;
address public nominatedOwner;
constructor(address _owner) {
require(_owner != address(0), "Owner address cannot be 0");
owner = _owner;
emit OwnerChanged(address(0), _owner);
}
function nominateNewOwner(address _owner) external virtual onlyOwner {
nominatedOwner = _owner;
emit OwnerNominated(_owner);
}
function acceptOwnership() external virtual {
require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership");
emit OwnerChanged(owner, nominatedOwner);
owner = nominatedOwner;
nominatedOwner = address(0);
}
modifier onlyOwner() {
_onlyOwner();
_;
}
function _onlyOwner() private view {
require(msg.sender == owner, "Only the contract owner may perform this action");
}
event OwnerNominated(address newOwner);
event OwnerChanged(address oldOwner, address newOwner);
}{
"remappings": [
"@openzeppelin/=node_modules/@openzeppelin/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/",
"openzeppelin-contracts/=node_modules/@openzeppelin/contracts/",
"solmate/=lib/solmate/src/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "london",
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"contract IAdminProxy","name":"_adminProxy","type":"address"},{"internalType":"contract IDeploymentController","name":"_deploymentController","type":"address"},{"internalType":"contract IVaultRegistry","name":"_vaultRegistry","type":"address"},{"internalType":"contract IPermissionRegistry","name":"_permissionRegistry","type":"address"},{"internalType":"contract IMultiRewardEscrow","name":"_escrow","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayLengthMismatch","type":"error"},{"inputs":[{"internalType":"address","name":"adapter","type":"address"}],"name":"DoesntExist","type":"error"},{"inputs":[],"name":"InvalidConfig","type":"error"},{"inputs":[{"internalType":"address","name":"deploymentController","type":"address"}],"name":"InvalidDeploymentController","type":"error"},{"inputs":[{"internalType":"uint256","name":"cooldown","type":"uint256"}],"name":"InvalidHarvestCooldown","type":"error"},{"inputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"name":"InvalidPerformanceFee","type":"error"},{"inputs":[{"internalType":"address","name":"subject","type":"address"}],"name":"NotAllowed","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"NotSubmitter","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"NotSubmitterNorOwner","type":"error"},{"inputs":[{"internalType":"bytes32","name":"templateKey","type":"bytes32"}],"name":"SameKey","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"oldKey","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"newKey","type":"bytes32"}],"name":"ActiveTemplateIdChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldController","type":"address"},{"indexed":false,"internalType":"address","name":"newController","type":"address"}],"name":"DeploymentControllerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldCooldown","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newCooldown","type":"uint256"}],"name":"HarvestCooldownChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"PerformanceFeeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"address","name":"staking","type":"address"},{"indexed":true,"internalType":"address","name":"adapter","type":"address"}],"name":"VaultDeployed","type":"event"},{"inputs":[],"name":"ADAPTER","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKING","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STRATEGY","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VAULT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptAdminProxyOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"activeTemplateId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"vaults","type":"address[]"},{"internalType":"bytes[]","name":"rewardTokenData","type":"bytes[]"}],"name":"addStakingRewardsTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"templateCategories","type":"bytes32[]"}],"name":"addTemplateCategories","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"adminProxy","outputs":[{"internalType":"contract IAdminProxy","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"vaults","type":"address[]"},{"internalType":"contract IERC20Upgradeable[]","name":"rewardTokens","type":"address[]"},{"internalType":"uint160[]","name":"rewardsSpeeds","type":"uint160[]"}],"name":"changeStakingRewardsSpeeds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"vaults","type":"address[]"}],"name":"changeVaultAdapters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"vaults","type":"address[]"}],"name":"changeVaultFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cloneRegistry","outputs":[{"internalType":"contract ICloneRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Upgradeable","name":"asset","type":"address"},{"components":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct DeploymentArgs","name":"adapterData","type":"tuple"},{"components":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct DeploymentArgs","name":"strategyData","type":"tuple"},{"internalType":"uint256","name":"initialDeposit","type":"uint256"}],"name":"deployAdapter","outputs":[{"internalType":"address","name":"adapter","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Upgradeable","name":"asset","type":"address"}],"name":"deployStaking","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20Upgradeable","name":"asset","type":"address"},{"internalType":"contract IERC4626Upgradeable","name":"adapter","type":"address"},{"components":[{"internalType":"uint64","name":"deposit","type":"uint64"},{"internalType":"uint64","name":"withdrawal","type":"uint64"},{"internalType":"uint64","name":"management","type":"uint64"},{"internalType":"uint64","name":"performance","type":"uint64"}],"internalType":"struct VaultFees","name":"fees","type":"tuple"},{"internalType":"address","name":"feeRecipient","type":"address"},{"internalType":"uint256","name":"depositLimit","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"internalType":"struct VaultInitParams","name":"vaultData","type":"tuple"},{"components":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct DeploymentArgs","name":"adapterData","type":"tuple"},{"components":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct DeploymentArgs","name":"strategyData","type":"tuple"},{"internalType":"bool","name":"deployStaking","type":"bool"},{"internalType":"bytes","name":"rewardsData","type":"bytes"},{"components":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"staking","type":"address"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"string","name":"metadataCID","type":"string"},{"internalType":"address[8]","name":"swapTokenAddresses","type":"address[8]"},{"internalType":"address","name":"swapAddress","type":"address"},{"internalType":"uint256","name":"exchange","type":"uint256"}],"internalType":"struct VaultMetadata","name":"metadata","type":"tuple"},{"internalType":"uint256","name":"initialDeposit","type":"uint256"}],"name":"deployVault","outputs":[{"internalType":"address","name":"vault","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deploymentController","outputs":[{"internalType":"contract IDeploymentController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"escrow","outputs":[{"internalType":"contract IMultiRewardEscrow","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"vaults","type":"address[]"},{"internalType":"contract IERC20Upgradeable[]","name":"rewardTokens","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"fundStakingRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"harvestCooldown","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"nominateNewAdminProxyOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"vaults","type":"address[]"}],"name":"pauseAdapters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"vaults","type":"address[]"}],"name":"pauseVaults","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"performanceFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"permissionRegistry","outputs":[{"internalType":"contract IPermissionRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"vaults","type":"address[]"},{"internalType":"contract IERC4626Upgradeable[]","name":"newAdapter","type":"address[]"}],"name":"proposeVaultAdapters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"vaults","type":"address[]"},{"components":[{"internalType":"uint64","name":"deposit","type":"uint64"},{"internalType":"uint64","name":"withdrawal","type":"uint64"},{"internalType":"uint64","name":"management","type":"uint64"},{"internalType":"uint64","name":"performance","type":"uint64"}],"internalType":"struct VaultFees[]","name":"fees","type":"tuple[]"}],"name":"proposeVaultFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"templateCategory","type":"bytes32"},{"internalType":"bytes32","name":"templateId","type":"bytes32"}],"name":"setActiveTemplateId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"adapters","type":"address[]"}],"name":"setAdapterHarvestCooldowns","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"adapters","type":"address[]"}],"name":"setAdapterPerformanceFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IDeploymentController","name":"_deploymentController","type":"address"}],"name":"setDeploymentController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Upgradeable[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"fees","type":"uint256[]"}],"name":"setEscrowTokenFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newCooldown","type":"uint256"}],"name":"setHarvestCooldown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"setPerformanceFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"components":[{"internalType":"bool","name":"endorsed","type":"bool"},{"internalType":"bool","name":"rejected","type":"bool"}],"internalType":"struct Permission[]","name":"newPermissions","type":"tuple[]"}],"name":"setPermissions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"vaults","type":"address[]"},{"internalType":"uint256[]","name":"depositLimits","type":"uint256[]"}],"name":"setVaultDepositLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"vaults","type":"address[]"},{"internalType":"address[]","name":"feeRecipients","type":"address[]"}],"name":"setVaultFeeRecipients","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"vaults","type":"address[]"},{"internalType":"uint256[]","name":"quitPeriods","type":"uint256[]"}],"name":"setVaultQuitPeriods","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"templateRegistry","outputs":[{"internalType":"contract ITemplateRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"templateCategories","type":"bytes32[]"},{"internalType":"bytes32[]","name":"templateIds","type":"bytes32[]"}],"name":"toggleTemplateEndorsements","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"vaults","type":"address[]"}],"name":"unpauseAdapters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"vaults","type":"address[]"}],"name":"unpauseVaults","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vaultRegistry","outputs":[{"internalType":"contract IVaultRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
6101206040526415985d5b1d60da1b6080526620b230b83a32b960c91b60a05267537472617465677960c01b60c052665374616b696e6760c81b60e05263d76fad2360e01b610100523480156200005557600080fd5b506040516200591d3803806200591d833981016040819052620000789162000541565b856001600160a01b038116620000d55760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f7420626520300000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03831690811782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a150600480546001600160a01b038088166001600160a01b03199283161790925560028054868416908316179055600a805485841690831617905560038054928416929091169190911790556200018284620001c8565b505060e0516000908152600b6020526040808220714d756c74695265776172645374616b696e6760701b90556080518252902061563160f01b9055506200075d92505050565b6001600160a01b0381161580620001ec57506007546001600160a01b038281169116145b15620002175760405163e72ce82960e01b81526001600160a01b0382166004820152602401620000cc565b600754604080516001600160a01b03928316815291831660208301527f56fa229ccbaf666061902dae11d3700b32263d110cdaf9445834d40b6bf00c54910160405180910390a16007546001600160a01b0316156200027b576200027b81620003a9565b600780546001600160a01b0319166001600160a01b038316908117909155604080516311784f7d60e01b815290516311784f7d916004808201926020929091908290030181865afa158015620002d5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002fb9190620005d5565b600860006101000a8154816001600160a01b0302191690836001600160a01b03160217905550806001600160a01b031663a0af81f06040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000360573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003869190620005d5565b600980546001600160a01b0319166001600160a01b039290921691909117905550565b60048054600754604080516001600160a01b0386811660248084019190915283518084039091018152604490920183526020820180516001600160e01b031663c30ebb1760e01b1790529151631cff79cd60e01b815293821694631cff79cd946200041a949390931692016200062f565b6000604051808303816000875af11580156200043a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000464919081019062000689565b5050600480546040805160206024820181905260006044808401919091528351808403909101815260649092018352810180516001600160e01b0316630cf1cfe360e01b1790529051631cff79cd60e01b81526001600160a01b0390921692631cff79cd92620004d99286929091016200062f565b6000604051808303816000875af1158015620004f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000523919081019062000689565b505050565b6001600160a01b03811681146200053e57600080fd5b50565b60008060008060008060c087890312156200055b57600080fd5b8651620005688162000528565b60208801519096506200057b8162000528565b60408801519095506200058e8162000528565b6060880151909450620005a18162000528565b6080880151909350620005b48162000528565b60a0880151909250620005c78162000528565b809150509295509295509295565b600060208284031215620005e857600080fd5b8151620005f58162000528565b9392505050565b60005b8381101562000619578181015183820152602001620005ff565b8381111562000629576000848401525b50505050565b60018060a01b038316815260406020820152600082518060408401526200065e816060850160208701620005fc565b601f01601f1916919091016060019392505050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200069d57600080fd5b82518015158114620006ae57600080fd5b60208401519092506001600160401b0380821115620006cc57600080fd5b818501915085601f830112620006e157600080fd5b815181811115620006f657620006f662000673565b604051601f8201601f19908116603f0116810190838211818310171562000721576200072162000673565b816040528281528860208487010111156200073b57600080fd5b6200074e836020830160208801620005fc565b80955050505050509250929050565b60805160a05160c05160e0516101005161513c620007e1600039600081816130050152818161359c0152818161387001526138b80152600081816105100152612fa001526000818161038b01528181613222015261381b01526000818161030a015281816138da0152613ba401526000818161040701526134ec015261513c6000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c806379ba509711610167578063be283e66116100ce578063d7fe6a8511610087578063d7fe6a8514610610578063e2fdcc1714610623578063e45e1b9414610636578063ebf0f0db1461063e578063ed8725d914610651578063f03ff65e1461066457600080fd5b8063be283e661461059e578063c0cbe791146105b1578063c52f4f34146105c4578063ccc0f886146105d7578063cdd7b38a146105ea578063d643ad32146105fd57600080fd5b806397610f301161012057806397610f301461050b5780639b34dbb014610532578063a0af81f014610552578063a2a5268514610565578063a52f0ead14610578578063b55a5c1c1461058b57600080fd5b806379ba5097146104ae5780637bd0703d146104b6578063806aeabb146104c957806387788782146104dc5780638ba684e0146104e55780638da5cb5b146104f857600080fd5b806323e45a621161020b578063557d5f93116101c4578063557d5f931461043c5780635c456e161461044f5780635dcc700f146104625780636d9567631461047557806370897b23146104885780637682bf751461049b57600080fd5b806323e45a62146103b65780632c3f064f146103c957806338433483146103dc5780633c27cc18146103ef578063411557d11461040257806353a47bb71461042957600080fd5b80631249ed231161025d5780631249ed231461033a5780631433117e1461034d57806315e455f8146103605780631627540c14610373578063185025ef14610386578063234d200f146103ad57600080fd5b8063012bf50d1461029a5780630a95d1ff146102ca57806310e36500146102df57806311784f7d146102f2578063121193f014610305575b600080fd5b6007546102ad906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6102dd6102d8366004613f61565b610677565b005b6102dd6102ed366004613f61565b6106e3565b6008546102ad906001600160a01b031681565b61032c7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016102c1565b6102ad610348366004613f61565b6106f7565b6102dd61035b366004613fc9565b610895565b6102dd61036e366004613fc9565b610a14565b6102dd610381366004613f61565b610ae3565b61032c7f000000000000000000000000000000000000000000000000000000000000000081565b61032c60065481565b6102dd6103c4366004614034565b610b3f565b6102dd6103d7366004614034565b610c55565b6102dd6103ea366004614075565b610d55565b6102dd6103fd366004614034565b610d97565b61032c7f000000000000000000000000000000000000000000000000000000000000000081565b6001546102ad906001600160a01b031681565b6102ad61044a3660046142ce565b610e87565b6102dd61045d366004614034565b611031565b6102dd610470366004614034565b611121565b6102dd610483366004614034565b61122b565b6102dd61049636600461434b565b61137e565b6102dd6104a9366004613fc9565b6113f3565b6102dd61153e565b6102dd6104c4366004613fc9565b611628565b6102dd6104d7366004614364565b611769565b61032c60055481565b6102dd6104f3366004614034565b6118b1565b6000546102ad906001600160a01b031681565b61032c7f000000000000000000000000000000000000000000000000000000000000000081565b61032c61054036600461434b565b600b6020526000908152604090205481565b6009546102ad906001600160a01b031681565b6102dd610573366004613fc9565b6119b1565b6102dd610586366004614034565b611afc565b600a546102ad906001600160a01b031681565b6102dd6105ac3660046143ee565b611c4f565b6102dd6105bf3660046143ee565b611dc7565b6004546102ad906001600160a01b031681565b6102dd6105e5366004614534565b612027565b6002546102ad906001600160a01b031681565b6102dd61060b36600461434b565b61236b565b6102dd61061e366004614034565b6123db565b6003546102ad906001600160a01b031681565b6102dd6124eb565b6102dd61064c3660046145f5565b612542565b6102ad61065f36600461481d565b6125cb565b6102dd610672366004613fc9565b6128f2565b61067f612b4f565b60048054604051630589d50360e21b81526001600160a01b0384811693820193909352911690631627540c90602401600060405180830381600087803b1580156106c857600080fd5b505af11580156106dc573d6000803e3d6000fd5b5050505050565b6106eb612b4f565b6106f481612bc3565b50565b600a5460405163854b89d560e01b8152600160048201526000916001600160a01b03169063854b89d590602401602060405180830381865afa158015610741573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107659190614907565b6107da57600a546040516305d7c29760e01b81523360048201526001600160a01b03909116906305d7c29790602401602060405180830381865afa1580156107b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d59190614907565b610848565b600a5460405163854b89d560e01b81523360048201526001600160a01b039091169063854b89d590602401602060405180830381865afa158015610822573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108469190614907565b155b1561086d5760405163fa5cd00f60e01b81523360048201526024015b60405180910390fd5b61087682612d98565b60075461088d9083906001600160a01b0316612f9b565b90505b919050565b826108a360ff82168361311a565b60005b8160ff168160ff161015610a0c576108e686868360ff168181106108cc576108cc614924565b90506020020160208101906108e19190613f61565b61313e565b506004546001600160a01b0316631cff79cd878760ff851681811061090d5761090d614924565b90506020020160208101906109229190613f61565b63e74b981b60e01b878760ff871681811061093f5761093f614924565b90506020020160208101906109549190613f61565b6040516001600160a01b03909116602482015260440160408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b90921682526109b09291600401614992565b6000604051808303816000875af11580156109cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109f791908101906149e6565b50508080610a0490614a56565b9150506108a6565b505050505050565b610a1c612b4f565b6004546003546040516001600160a01b0392831692631cff79cd9216906305be054960e21b90610a56908990899089908990602401614a75565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b9092168252610a9c9291600401614992565b6000604051808303816000875af1158015610abb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a0c91908101906149e6565b610aeb612b4f565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b610b47612b4f565b8060005b8160ff16811015610c4f576004546001600160a01b0316631cff79cd858584818110610b7957610b79614924565b9050602002016020810190610b8e9190613f61565b600654604051636b21d69960e11b91610bad9160240190815260200190565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b9092168252610bf39291600401614992565b6000604051808303816000875af1158015610c12573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c3a91908101906149e6565b50508080610c4790614af9565b915050610b4b565b50505050565b8060005b8160ff16811015610c4f57610c798484838181106108cc576108cc614924565b506004546001600160a01b0316631cff79cd858584818110610c9d57610c9d614924565b9050602002016020810190610cb29190613f61565b6040805160048082526024820183526020820180516001600160e01b0316631fa5d41d60e11b179052915160e085901b6001600160e01b0319168152610cf9939201614992565b6000604051808303816000875af1158015610d18573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d4091908101906149e6565b50508080610d4d90614af9565b915050610c59565b610d5d612b4f565b600454600a546040516001600160a01b0392831692631cff79cd921690633843348360e01b90610a56908990899089908990602401614b12565b8060005b8160ff168160ff161015610c4f576004546001600160a01b0316631cff79cd858560ff8516818110610dcf57610dcf614924565b9050602002016020810190610de49190613f61565b6040805160048082526024820183526020820180516001600160e01b0316630390ff7560e51b179052915160e085901b6001600160e01b0319168152610e2b939201614992565b6000604051808303816000875af1158015610e4a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610e7291908101906149e6565b50508080610e7f90614a56565b915050610d9b565b600a5460405163854b89d560e01b8152600160048201526000916001600160a01b03169063854b89d590602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef59190614907565b610f6a57600a546040516305d7c29760e01b81523360048201526001600160a01b03909116906305d7c29790602401602060405180830381865afa158015610f41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f659190614907565b610fd8565b600a5460405163854b89d560e01b81523360048201526001600160a01b039091169063854b89d590602401602060405180830381865afa158015610fb2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd69190614907565b155b15610ff85760405163fa5cd00f60e01b8152336004820152602401610864565b61100185612d98565b60075461101c908690869086906001600160a01b03166131f2565b9050611029828683613303565b949350505050565b8060005b8160ff168160ff161015610c4f576004546001600160a01b0316631cff79cd858560ff851681811061106957611069614924565b905060200201602081019061107e9190613f61565b6040805160048082526024820183526020820180516001600160e01b03166308a5a9c960e11b179052915160e085901b6001600160e01b03191681526110c5939201614992565b6000604051808303816000875af11580156110e4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261110c91908101906149e6565b5050808061111990614a56565b915050611035565b611129612b4f565b6007546001600160a01b03168160005b8160ff168110156106dc576004546001600160a01b0316631cff79cd8463a3f8344960e01b88888681811061117057611170614924565b9050602002013560405160240161118991815260200190565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b90921682526111cf9291600401614992565b6000604051808303816000875af11580156111ee573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261121691908101906149e6565b5050808061122390614af9565b915050611139565b611233612b4f565b8060005b8160ff16811015610c4f576004546001600160a01b0316631cff79cd85858481811061126557611265614924565b905060200201602081019061127a9190613f61565b6001600160a01b03166303eadcfc6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112db9190614bc3565b6040805160048082526024820183526020820180516001600160e01b0316631fa5d41d60e11b179052915160e085901b6001600160e01b0319168152611322939201614992565b6000604051808303816000875af1158015611341573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261136991908101906149e6565b5050808061137690614af9565b915050611237565b611386612b4f565b6702c68af0bb1400008111156113b257604051630a7e67f960e21b815260048101829052602401610864565b60055460408051918252602082018390527f44e5243903d4f21681121bff9dd91691edc7fa0b9d87cc40d6d65f1755a9b1b3910160405180910390a1600555565b8261140160ff82168361311a565b60005b8160ff168160ff161015610a0c5761142a86868360ff168181106108cc576108cc614924565b506004546001600160a01b0316631cff79cd878760ff851681811061145157611451614924565b90506020020160208101906114669190613f61565b633b8abce960e01b878760ff871681811061148357611483614924565b9050602002013560405160240161149c91815260200190565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b90921682526114e29291600401614992565b6000604051808303816000875af1158015611501573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261152991908101906149e6565b5050808061153690614a56565b915050611404565b6001546001600160a01b031633146115b65760405162461bcd60e51b815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527402063616e20616363657074206f776e65727368697605c1b6064820152608401610864565b600054600154604080516001600160a01b0393841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b611630612b4f565b8261163e60ff82168361311a565b6007546001600160a01b031660005b8260ff16811015611760576004546001600160a01b0316631cff79cd83632b0408fd60e11b8a8a8681811061168457611684614924565b9050602002013589898781811061169d5761169d614924565b905060200201356040516024016116be929190918252602082015260400190565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b90921682526117049291600401614992565b6000604051808303816000875af1158015611723573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261174b91908101906149e6565b5050808061175890614af9565b91505061164d565b50505050505050565b8261177760ff82168361311a565b60005b8160ff168160ff161015610a0c576117a086868360ff168181106108cc576108cc614924565b506004546001600160a01b0316631cff79cd878760ff85168181106117c7576117c7614924565b90506020020160208101906117dc9190613f61565b634469aa7d60e11b878760ff87168181106117f9576117f9614924565b90506080020160405160240161180f9190614be0565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b90921682526118559291600401614992565b6000604051808303816000875af1158015611874573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261189c91908101906149e6565b505080806118a990614a56565b91505061177a565b8060005b8160ff16811015610c4f576118d58484838181106108cc576108cc614924565b506004546001600160a01b0316631cff79cd8585848181106118f9576118f9614924565b905060200201602081019061190e9190613f61565b6040805160048082526024820183526020820180516001600160e01b0316638456cb5960e01b179052915160e085901b6001600160e01b0319168152611955939201614992565b6000604051808303816000875af1158015611974573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261199c91908101906149e6565b505080806119a990614af9565b9150506118b5565b826119bf60ff82168361311a565b60005b8160ff168160ff161015610a0c576119e886868360ff168181106108cc576108cc614924565b506004546001600160a01b0316631cff79cd878760ff8516818110611a0f57611a0f614924565b9050602002016020810190611a249190613f61565b63bdc8144b60e01b878760ff8716818110611a4157611a41614924565b90506020020135604051602401611a5a91815260200190565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b9092168252611aa09291600401614992565b6000604051808303816000875af1158015611abf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611ae791908101906149e6565b50508080611af490614a56565b9150506119c2565b611b04612b4f565b8060005b8160ff16811015610c4f576004546001600160a01b0316631cff79cd858584818110611b3657611b36614924565b9050602002016020810190611b4b9190613f61565b6001600160a01b03166303eadcfc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bac9190614bc3565b6040805160048082526024820183526020820180516001600160e01b0316638456cb5960e01b179052915160e085901b6001600160e01b0319168152611bf3939201614992565b6000604051808303816000875af1158015611c12573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611c3a91908101906149e6565b50508080611c4790614af9565b915050611b08565b84611c5d60ff82168561311a565b611c6a60ff82168361311a565b6000805b8260ff16811015611dbc57611c8e8989838181106108cc576108cc614924565b602001516004549092506001600160a01b0316631cff79cd8363725d641f60e01b8a8a86818110611cc157611cc1614924565b9050602002016020810190611cd69190613f61565b898987818110611ce857611ce8614924565b9050602002016020810190611cfd9190613f61565b6040516001600160a01b0392831660248201529116604482015260640160408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b9092168252611d609291600401614992565b6000604051808303816000875af1158015611d7f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611da791908101906149e6565b50508080611db490614af9565b915050611c6e565b505050505050505050565b84611dd560ff82168561311a565b611de260ff82168361311a565b6000805b8260ff16811015611dbc576002546001600160a01b0316630eb9af388a8a84818110611e1457611e14614924565b9050602002016020810190611e299190613f61565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401600060405180830381865afa158015611e6d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611e959190810190614ca8565b602001519150868682818110611ead57611ead614924565b9050602002016020810190611ec29190613f61565b6001600160a01b03166323b872dd3330888886818110611ee457611ee4614924565b6040516001600160e01b031960e088901b1681526001600160a01b039586166004820152949093166024850152506020909102013560448201526064016020604051808303816000875af1158015611f40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f649190614907565b50816001600160a01b031663a77cc3b3888884818110611f8657611f86614924565b9050602002016020810190611f9b9190613f61565b878785818110611fad57611fad614924565b6040516001600160e01b031960e087901b1681526001600160a01b0390941660048501526020029190910135602483015250604401600060405180830381600087803b158015611ffc57600080fd5b505af1158015612010573d6000803e3d6000fd5b50505050808061201f90614af9565b915050611de6565b6120338251825161311a565b8151600090815b8160ff168110156106dc5760008060008060008060008a888151811061206257612062614924565b602002602001015180602001905181019061207d9190614d78565b965096509650965096509650965061209487612d98565b6120b68c89815181106120a9576120a9614924565b6020026020010151613408565b60209081015160048054604080516001600160a01b038086166024830152600019604480840191909152835180840390910181526064909201835295810180516001600160e01b031663095ea7b360e01b1790529051631cff79cd60e01b8152939e50931692631cff79cd9261212f928c929101614992565b6000604051808303816000875af115801561214e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261217691908101906149e6565b505060405163095ea7b360e01b81526001600160a01b038b81166004830152600019602483015288169063095ea7b3906044016020604051808303816000875af11580156121c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ec9190614907565b50600480546040516323b872dd60e01b815233928101929092526001600160a01b039081166024830152604482018790528816906323b872dd906064016020604051808303816000875af1158015612248573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061226c9190614907565b5060048054604080516001600160a01b038b811660248301528a81166044830152606482018a905288151560848301526001600160e01b0388811660a484015262ffffff881660c484015260e48084018890528451808503909101815261010490930184526020830180519091166321c732bd60e21b1790529151631cff79cd60e01b81529190921692631cff79cd92612308928f9201614992565b6000604051808303816000875af1158015612327573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261234f91908101906149e6565b505050505050505050808061236390614af9565b91505061203a565b612373612b4f565b6201518081111561239a57604051636a46e7e760e11b815260048101829052602401610864565b60065460408051918252602082018390527f8a8cb5791fe06275eeac010d52ee9c0c86497874dfb955d853987b17d63b1099910160405180910390a1600655565b6123e3612b4f565b8060005b8160ff16811015610c4f576004546001600160a01b0316631cff79cd85858481811061241557612415614924565b905060200201602081019061242a9190613f61565b6005546040516370897b2360e01b916124499160240190815260200190565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b909216825261248f9291600401614992565b6000604051808303816000875af11580156124ae573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124d691908101906149e6565b505080806124e390614af9565b9150506123e7565b60048054604080516379ba509760e01b815290516001600160a01b03909216926379ba509792828201926000929082900301818387803b15801561252e57600080fd5b505af1158015610c4f573d6000803e3d6000fd5b61254a612b4f565b6000828152600b602052604090205481810361257f576040516001629062fd60e01b0319815260048101839052602401610864565b60408051828152602081018490527f8a248e757d07a431570dfad8e7b8e3113b477629c38b0ff4f3dcfff3c1c298b5910160405180910390a1506000918252600b602052604090912055565b600a5460405163854b89d560e01b8152600160048201526000916001600160a01b03169063854b89d590602401602060405180830381865afa158015612615573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126399190614907565b6126ae57600a546040516305d7c29760e01b81523360048201526001600160a01b03909116906305d7c29790602401602060405180830381865afa158015612685573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126a99190614907565b61271c565b600a5460405163854b89d560e01b81523360048201526001600160a01b039091169063854b89d590602401602060405180830381865afa1580156126f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061271a9190614907565b155b1561273c5760405163fa5cd00f60e01b8152336004820152602401610864565b60075488516001600160a01b039091169061275690612d98565b60208901516001600160a01b0316158015906127eb575087511515806127eb575060085460208a015160405163016a578960e31b81526001600160a01b039182166004820152911690630b52bc4890602401602060405180830381865afa1580156127c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127e99190614907565b155b15612809576040516306b7c75960e31b815260040160405180910390fd5b87511561282d57885161281e908989846131f2565b6001600160a01b031660208a01525b61283789826134d5565b91506000861561284e5761284b8383612f9b565b90505b6128598382876135cf565b855115612888578661287e576040516306b7c75960e31b815260040160405180910390fd5b61288883876135f3565b89602001516001600160a01b0316816001600160a01b0316846001600160a01b03167f26ad9f07a47e389150a15677a365d64f42af0000b792c182ada6a3b5ab193a0b60405160405180910390a46128e5848b6000015185613303565b5050979650505050505050565b8261290060ff82168361311a565b6008546001600160a01b031660005b8260ff168160ff1610156117605761293587878360ff168181106108cc576108cc614924565b50816001600160a01b0316630b52bc4886868460ff1681811061295a5761295a614924565b905060200201602081019061296f9190613f61565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156129b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129d79190614907565b612a2a5784848260ff168181106129f0576129f0614924565b9050602002016020810190612a059190613f61565b604051631ad28c5760e11b81526001600160a01b039091166004820152602401610864565b6004546001600160a01b0316631cff79cd888860ff8516818110612a5057612a50614924565b9050602002016020810190612a659190613f61565b630a192d3960e01b888860ff8716818110612a8257612a82614924565b9050602002016020810190612a979190613f61565b6040516001600160a01b03909116602482015260440160408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b9092168252612af39291600401614992565b6000604051808303816000875af1158015612b12573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612b3a91908101906149e6565b50508080612b4790614a56565b91505061290f565b6000546001600160a01b03163314612bc15760405162461bcd60e51b815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201526e37b936903a3434b99030b1ba34b7b760891b6064820152608401610864565b565b6001600160a01b0381161580612be657506007546001600160a01b038281169116145b15612c0f5760405163e72ce82960e01b81526001600160a01b0382166004820152602401610864565b600754604080516001600160a01b03928316815291831660208301527f56fa229ccbaf666061902dae11d3700b32263d110cdaf9445834d40b6bf00c54910160405180910390a16007546001600160a01b031615612c7057612c70816136a1565b600780546001600160a01b0319166001600160a01b038316908117909155604080516311784f7d60e01b815290516311784f7d916004808201926020929091908290030181865afa158015612cc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ced9190614bc3565b600860006101000a8154816001600160a01b0302191690836001600160a01b03160217905550806001600160a01b031663a0af81f06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d759190614bc3565b600980546001600160a01b0319166001600160a01b039290921691909117905550565b600a5460405163854b89d560e01b8152600060048201526001600160a01b039091169063854b89d590602401602060405180830381865afa158015612de1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e059190614907565b612e7c57600a546040516305d7c29760e01b81526001600160a01b038381166004830152909116906305d7c29790602401602060405180830381865afa158015612e53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e779190614907565b612eec565b600a5460405163854b89d560e01b81526001600160a01b0383811660048301529091169063854b89d590602401602060405180830381865afa158015612ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eea9190614907565b155b80612f60575060085460405163016a578960e31b81526001600160a01b03838116600483015290911690630b52bc4890602401602060405180830381865afa158015612f3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f609190614907565b80612f7257506001600160a01b038116155b156106f45760405163fa5cd00f60e01b81526001600160a01b0382166004820152602401610864565b6004547f00000000000000000000000000000000000000000000000000000000000000006000818152600b60205260408082205460035491516001600160a01b0388811660248301529283166044820152919094166064820181905291938493631cff79cd9287927f0000000000000000000000000000000000000000000000000000000000000000929163c0c53b8b60e01b906084015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161307693929190602401614e14565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b90921682526130bc9291600401614992565b6000604051808303816000875af11580156130db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261310391908101906149e6565b915050808060200190518101906110299190614bc3565b80821461313a5760405163512509d360e11b815260040160405180910390fd5b5050565b613146613edf565b6002546040516301d735e760e31b81526001600160a01b03848116600483015290911690630eb9af3890602401600060405180830381865afa158015613190573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526131b89190810190614ca8565b905080604001516001600160a01b0316336001600160a01b03161461089057604051630b5024e560e11b8152336004820152602401610864565b6000806131fd613f22565b8451156132b05761320e8585613811565b600954865160405163a98a151760e01b81527f0000000000000000000000000000000000000000000000000000000000000000600482015260248101919091529193506001600160a01b03169063a98a151790604401600060405180830381865afa158015613281573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526132a99190810190614e99565b60a0015190505b6004546006546020808801516040516132f8948b946132e3948e946001600160a01b03909316938a938a92909101614f60565b60405160208183030381529060405286613898565b979650505050505050565b82156134035761331e6001600160a01b038316333086613a76565b60405163095ea7b360e01b81526001600160a01b0382811660048301526024820185905283169063095ea7b3906044016020604051808303816000875af115801561336d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133919190614907565b50604051636e553f6560e01b8152600481018490523360248201526001600160a01b03821690636e553f65906044016020604051808303816000875af11580156133df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4f9190614fdd565b505050565b613410613edf565b6002546040516301d735e760e31b81526001600160a01b03848116600483015290911690630eb9af3890602401600060405180830381865afa15801561345a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526134829190810190614ca8565b905080604001516001600160a01b0316336001600160a01b0316141580156134b557506000546001600160a01b03163314155b15610890576040516311d8f05f60e31b8152336004820152602401610864565b6004546001600160a01b0390811660a084018181527f00000000000000000000000000000000000000000000000000000000000000006000818152600b602090815260408083205481518a5189166024820152838b015189166044820152828b015180516001600160401b039081166064840152948101518516608483015292830151841660a482015260609283015190931660c484015290890151871660e48301526080890151610104830152935190951661012486015293849392631cff79cd9287927f00000000000000000000000000000000000000000000000000000000000000009290632d41b1e560e11b9061014401613033565b6001600160a01b038084168252821660208201523360408201526134038382613ad0565b6040805160018082528183019092526000916020808301908036833750506040805160018082528183019092529293506000929150602082015b606081526020019060019003908161362d579050509050838260008151811061365857613658614924565b60200260200101906001600160a01b031690816001600160a01b031681525050828160008151811061368c5761368c614924565b6020026020010181905250610c4f8282612027565b60048054600754604080516001600160a01b0386811660248084019190915283518084039091018152604490920183526020820180516001600160e01b031663c30ebb1760e01b1790529151631cff79cd60e01b815293821694631cff79cd9461371094939093169201614992565b6000604051808303816000875af115801561372f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261375791908101906149e6565b5050600480546040805160206024820181905260006044808401919091528351808403909101815260649092018352810180516001600160e01b0316630cf1cfe360e01b1790529051631cff79cd60e01b81526001600160a01b0390921692631cff79cd926137ca928692909101614992565b6000604051808303816000875af11580156137e9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261340391908101906149e6565b60045482516040517f000000000000000000000000000000000000000000000000000000000000000060248201526044810191909152606060648201526000608482018190529182916001600160a01b0390911690631cff79cd9085907f00000000000000000000000000000000000000000000000000000000000000009060a401613076565b600454835160009182916001600160a01b0390911690631cff79cd9085907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906139048b8b613b90565b60405160240161391693929190614e14565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b909216825261395c9291600401614992565b6000604051808303816000875af115801561397b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526139a391908101906149e6565b915050808060200190518101906139ba9190614bc3565b60048054600554604080516024808201939093528151808203909301835260440181526020820180516001600160e01b03166370897b2360e01b17905251631cff79cd60e01b81529395506001600160a01b0390911692631cff79cd92613a25928792909101614992565b6000604051808303816000875af1158015613a44573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613a6c91908101906149e6565b5050509392505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052610c4f908590613c8b565b6004546002546040516001600160a01b0392831692631cff79cd92169062a6bc5f60e71b90613b03908690602401614ff6565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b9092168252613b499291600401614992565b6000604051808303816000875af1158015613b68573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c4f91908101906149e6565b600954825160405163a98a151760e01b81527f000000000000000000000000000000000000000000000000000000000000000060048201526024810191909152606091631f1ccddf60e31b9184916001600160a01b03169063a98a151790604401600060405180830381865afa158015613c0e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613c369190810190614e99565b608001518560200151604051602401613c5193929190615099565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905092915050565b6000613ce0826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613d5d9092919063ffffffff16565b8051909150156134035780806020019051810190613cfe9190614907565b6134035760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610864565b6060613d6c8484600085613d76565b90505b9392505050565b606082471015613dd75760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610864565b600080866001600160a01b03168587604051613df391906150d7565b60006040518083038185875af1925050503d8060008114613e30576040519150601f19603f3d011682016040523d82523d6000602084013e613e35565b606091505b50915091506132f88783838760608315613eb0578251600003613ea9576001600160a01b0385163b613ea95760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610864565b5081611029565b6110298383815115613ec55781518083602001fd5b8060405162461bcd60e51b815260040161086491906150f3565b6040805160e0810182526000808252602082018190529181019190915260608082015260808101613f0e613f22565b815260006020820181905260409091015290565b6040518061010001604052806008906020820280368337509192915050565b6001600160a01b03811681146106f457600080fd5b803561089081613f41565b600060208284031215613f7357600080fd5b8135613d6f81613f41565b60008083601f840112613f9057600080fd5b5081356001600160401b03811115613fa757600080fd5b6020830191508360208260051b8501011115613fc257600080fd5b9250929050565b60008060008060408587031215613fdf57600080fd5b84356001600160401b0380821115613ff657600080fd5b61400288838901613f7e565b9096509450602087013591508082111561401b57600080fd5b5061402887828801613f7e565b95989497509550505050565b6000806020838503121561404757600080fd5b82356001600160401b0381111561405d57600080fd5b61406985828601613f7e565b90969095509350505050565b6000806000806040858703121561408b57600080fd5b84356001600160401b03808211156140a257600080fd5b6140ae88838901613f7e565b909650945060208701359150808211156140c757600080fd5b818701915087601f8301126140db57600080fd5b8135818111156140ea57600080fd5b8860208260061b85010111156140ff57600080fd5b95989497505060200194505050565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b03811182821017156141465761414661410e565b60405290565b604051608081016001600160401b03811182821017156141465761414661410e565b60405160e081016001600160401b03811182821017156141465761414661410e565b60405161010081016001600160401b03811182821017156141465761414661410e565b604051601f8201601f191681016001600160401b03811182821017156141db576141db61410e565b604052919050565b60006001600160401b038211156141fc576141fc61410e565b50601f01601f191660200190565b600082601f83011261421b57600080fd5b813561422e614229826141e3565b6141b3565b81815284602083860101111561424357600080fd5b816020850160208301376000918101602001919091529392505050565b60006040828403121561427257600080fd5b604051604081016001600160401b0382821081831117156142955761429561410e565b816040528293508435835260208501359150808211156142b457600080fd5b506142c18582860161420a565b6020830152505092915050565b600080600080608085870312156142e457600080fd5b84356142ef81613f41565b935060208501356001600160401b038082111561430b57600080fd5b61431788838901614260565b9450604087013591508082111561432d57600080fd5b5061433a87828801614260565b949793965093946060013593505050565b60006020828403121561435d57600080fd5b5035919050565b6000806000806040858703121561437a57600080fd5b84356001600160401b038082111561439157600080fd5b61439d88838901613f7e565b909650945060208701359150808211156143b657600080fd5b818701915087601f8301126143ca57600080fd5b8135818111156143d957600080fd5b8860208260071b85010111156140ff57600080fd5b6000806000806000806060878903121561440757600080fd5b86356001600160401b038082111561441e57600080fd5b61442a8a838b01613f7e565b9098509650602089013591508082111561444357600080fd5b61444f8a838b01613f7e565b9096509450604089013591508082111561446857600080fd5b5061447589828a01613f7e565b979a9699509497509295939492505050565b60006001600160401b038211156144a0576144a061410e565b5060051b60200190565b600082601f8301126144bb57600080fd5b813560206144cb61422983614487565b82815260059290921b840181019181810190868411156144ea57600080fd5b8286015b848110156145295780356001600160401b0381111561450d5760008081fd5b61451b8986838b010161420a565b8452509183019183016144ee565b509695505050505050565b6000806040838503121561454757600080fd5b82356001600160401b038082111561455e57600080fd5b818501915085601f83011261457257600080fd5b8135602061458261422983614487565b82815260059290921b840181019181810190898411156145a157600080fd5b948201945b838610156145c85785356145b981613f41565b825294820194908201906145a6565b965050860135925050808211156145de57600080fd5b506145eb858286016144aa565b9150509250929050565b6000806040838503121561460857600080fd5b50508035926020909101359150565b80356001600160401b038116811461089057600080fd5b600081830361012081121561464257600080fd5b61464a614124565b9150823561465781613f41565b8252602083013561466781613f41565b60208301526080603f198201121561467e57600080fd5b5061468761414c565b61469360408401614617565b81526146a160608401614617565b60208201526146b260808401614617565b60408201526146c360a08401614617565b606082015260408201526146d960c08301613f56565b606082015260e082013560808201526146f56101008301613f56565b60a082015292915050565b80151581146106f457600080fd5b803561089081614700565b600082601f83011261472a57600080fd5b614732614190565b8061010084018581111561474557600080fd5b845b8181101561476857803561475a81613f41565b845260209384019301614747565b509095945050505050565b60006101c0828403121561478657600080fd5b61478e61416e565b905061479982613f56565b81526147a760208301613f56565b60208201526147b860408301613f56565b604082015260608201356001600160401b038111156147d657600080fd5b6147e28482850161420a565b6060830152506147f58360808401614719565b60808201526148076101808301613f56565b60a08201526101a082013560c082015292915050565b60008060008060008060006101e0888a03121561483957600080fd5b614843898961462e565b96506101208801356001600160401b038082111561486057600080fd5b61486c8b838c01614260565b97506101408a013591508082111561488357600080fd5b61488f8b838c01614260565b965061489e6101608b0161470e565b95506101808a01359150808211156148b557600080fd5b6148c18b838c0161420a565b94506101a08a01359150808211156148d857600080fd5b506148e58a828b01614773565b9250506101c0880135905092959891949750929550565b805161089081614700565b60006020828403121561491957600080fd5b8151613d6f81614700565b634e487b7160e01b600052603260045260246000fd5b60005b8381101561495557818101518382015260200161493d565b83811115610c4f5750506000910152565b6000815180845261497e81602086016020860161493a565b601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201819052600090613d6c90830184614966565b60006149c4614229846141e3565b90508281528383830111156149d857600080fd5b613d6f83602083018461493a565b600080604083850312156149f957600080fd5b8251614a0481614700565b60208401519092506001600160401b03811115614a2057600080fd5b8301601f81018513614a3157600080fd5b6145eb858251602084016149b6565b634e487b7160e01b600052601160045260246000fd5b600060ff821660ff8103614a6c57614a6c614a40565b60010192915050565b6040808252810184905260008560608301825b87811015614ab8578235614a9b81613f41565b6001600160a01b0316825260209283019290910190600101614a88565b5083810360208501528481526001600160fb1b03851115614ad857600080fd5b8460051b915081866020830137600091016020019081529695505050505050565b600060018201614b0b57614b0b614a40565b5060010190565b60408082528181018590526000908660608401835b88811015614b57578235614b3a81613f41565b6001600160a01b0316825260209283019290910190600101614b27565b5084810360208681019190915286825291508690820160005b87811015614baa578235614b8381614700565b1515825282840135614b9481614700565b1515828501529184019190840190600101614b70565b509998505050505050505050565b805161089081613f41565b600060208284031215614bd557600080fd5b8151613d6f81613f41565b608081016001600160401b0380614bf685614617565b16835280614c0660208601614617565b16602084015280614c1960408601614617565b16604084015280614c2c60608601614617565b1660608401525092915050565b600082601f830112614c4a57600080fd5b613d6f838351602085016149b6565b600082601f830112614c6a57600080fd5b614c72614190565b80610100840185811115614c8557600080fd5b845b81811015614768578051614c9a81613f41565b845260209384019301614c87565b600060208284031215614cba57600080fd5b81516001600160401b0380821115614cd157600080fd5b908301906101c08286031215614ce657600080fd5b614cee61416e565b614cf783614bb8565b8152614d0560208401614bb8565b6020820152614d1660408401614bb8565b6040820152606083015182811115614d2d57600080fd5b614d3987828601614c39565b606083015250614d4c8660808501614c59565b6080820152614d5e6101808401614bb8565b60a08201526101a0929092015160c0830152509392505050565b600080600080600080600060e0888a031215614d9357600080fd5b8751614d9e81613f41565b6020890151909750614daf81613f41565b604089015160608a01519197509550614dc781614700565b60808901519094506001600160e01b0381168114614de457600080fd5b60a089015190935062ffffff81168114614dfd57600080fd5b8092505060c0880151905092959891949750929550565b838152826020820152606060408201526000614e336060830184614966565b95945050505050565b600082601f830112614e4d57600080fd5b614e55614190565b80610100840185811115614e6857600080fd5b845b818110156147685780516001600160e01b031981168114614e8b5760008081fd5b845260209384019301614e6a565b600060208284031215614eab57600080fd5b81516001600160401b0380821115614ec257600080fd5b908301906101a08286031215614ed757600080fd5b614edf614124565b8251614eea81613f41565b81526020830151614efa81614700565b6020820152604083015182811115614f1157600080fd5b614f1d87828601614c39565b604083015250614f2f606084016148fc565b6060820152614f4060808401614bb8565b6080820152614f528660a08501614e3c565b60a082015295945050505050565b60006101a060018060a01b03808a1684526020818a168186015281891660408601528760608601526080850191508660005b6008811015614fb95781516001600160e01b03191684529282019290820190600101614f92565b5050505080610180840152614fd081840185614966565b9998505050505050505050565b600060208284031215614fef57600080fd5b5051919050565b6000602080835260018060a01b038085511682850152808286015116604085015280604086015116606085015260608501516101c080608087015261503f6101e0870183614966565b9150608087015160a0870160005b600881101561506c57825186168252918601919086019060010161504d565b50505060a08701516001600160a01b03166101a087015260c0909601519590940194909452509092915050565b6060815260006150ac6060830186614966565b6001600160a01b038516602084015282810360408401526150cd8185614966565b9695505050505050565b600082516150e981846020870161493a565b9190910192915050565b602081526000613d6f602083018461496656fea2646970667358221220ac0d0f4777d8573437831a50ca9370208ad9901e63f7b1383acc8aa770066cba64736f6c634300080f003300000000000000000000000022f5413c075ccd56d575a54763831c4c27a37bdb000000000000000000000000564fbe59c448743fa9382e691a0320458f6dcde5000000000000000000000000a8c5815f6ea5f7a1551541b0d7f970d546126bdb000000000000000000000000007318dc89b314b47609c684260cfbfbcd4128640000000000000000000000007a33b5b57c8b235a3519e6c010027c5cebb15cb4000000000000000000000000f76b7de04a76609766f437d2eb6021748c0598af
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102955760003560e01c806379ba509711610167578063be283e66116100ce578063d7fe6a8511610087578063d7fe6a8514610610578063e2fdcc1714610623578063e45e1b9414610636578063ebf0f0db1461063e578063ed8725d914610651578063f03ff65e1461066457600080fd5b8063be283e661461059e578063c0cbe791146105b1578063c52f4f34146105c4578063ccc0f886146105d7578063cdd7b38a146105ea578063d643ad32146105fd57600080fd5b806397610f301161012057806397610f301461050b5780639b34dbb014610532578063a0af81f014610552578063a2a5268514610565578063a52f0ead14610578578063b55a5c1c1461058b57600080fd5b806379ba5097146104ae5780637bd0703d146104b6578063806aeabb146104c957806387788782146104dc5780638ba684e0146104e55780638da5cb5b146104f857600080fd5b806323e45a621161020b578063557d5f93116101c4578063557d5f931461043c5780635c456e161461044f5780635dcc700f146104625780636d9567631461047557806370897b23146104885780637682bf751461049b57600080fd5b806323e45a62146103b65780632c3f064f146103c957806338433483146103dc5780633c27cc18146103ef578063411557d11461040257806353a47bb71461042957600080fd5b80631249ed231161025d5780631249ed231461033a5780631433117e1461034d57806315e455f8146103605780631627540c14610373578063185025ef14610386578063234d200f146103ad57600080fd5b8063012bf50d1461029a5780630a95d1ff146102ca57806310e36500146102df57806311784f7d146102f2578063121193f014610305575b600080fd5b6007546102ad906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6102dd6102d8366004613f61565b610677565b005b6102dd6102ed366004613f61565b6106e3565b6008546102ad906001600160a01b031681565b61032c7f416461707465720000000000000000000000000000000000000000000000000081565b6040519081526020016102c1565b6102ad610348366004613f61565b6106f7565b6102dd61035b366004613fc9565b610895565b6102dd61036e366004613fc9565b610a14565b6102dd610381366004613f61565b610ae3565b61032c7f537472617465677900000000000000000000000000000000000000000000000081565b61032c60065481565b6102dd6103c4366004614034565b610b3f565b6102dd6103d7366004614034565b610c55565b6102dd6103ea366004614075565b610d55565b6102dd6103fd366004614034565b610d97565b61032c7f5661756c7400000000000000000000000000000000000000000000000000000081565b6001546102ad906001600160a01b031681565b6102ad61044a3660046142ce565b610e87565b6102dd61045d366004614034565b611031565b6102dd610470366004614034565b611121565b6102dd610483366004614034565b61122b565b6102dd61049636600461434b565b61137e565b6102dd6104a9366004613fc9565b6113f3565b6102dd61153e565b6102dd6104c4366004613fc9565b611628565b6102dd6104d7366004614364565b611769565b61032c60055481565b6102dd6104f3366004614034565b6118b1565b6000546102ad906001600160a01b031681565b61032c7f5374616b696e670000000000000000000000000000000000000000000000000081565b61032c61054036600461434b565b600b6020526000908152604090205481565b6009546102ad906001600160a01b031681565b6102dd610573366004613fc9565b6119b1565b6102dd610586366004614034565b611afc565b600a546102ad906001600160a01b031681565b6102dd6105ac3660046143ee565b611c4f565b6102dd6105bf3660046143ee565b611dc7565b6004546102ad906001600160a01b031681565b6102dd6105e5366004614534565b612027565b6002546102ad906001600160a01b031681565b6102dd61060b36600461434b565b61236b565b6102dd61061e366004614034565b6123db565b6003546102ad906001600160a01b031681565b6102dd6124eb565b6102dd61064c3660046145f5565b612542565b6102ad61065f36600461481d565b6125cb565b6102dd610672366004613fc9565b6128f2565b61067f612b4f565b60048054604051630589d50360e21b81526001600160a01b0384811693820193909352911690631627540c90602401600060405180830381600087803b1580156106c857600080fd5b505af11580156106dc573d6000803e3d6000fd5b5050505050565b6106eb612b4f565b6106f481612bc3565b50565b600a5460405163854b89d560e01b8152600160048201526000916001600160a01b03169063854b89d590602401602060405180830381865afa158015610741573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107659190614907565b6107da57600a546040516305d7c29760e01b81523360048201526001600160a01b03909116906305d7c29790602401602060405180830381865afa1580156107b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d59190614907565b610848565b600a5460405163854b89d560e01b81523360048201526001600160a01b039091169063854b89d590602401602060405180830381865afa158015610822573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108469190614907565b155b1561086d5760405163fa5cd00f60e01b81523360048201526024015b60405180910390fd5b61087682612d98565b60075461088d9083906001600160a01b0316612f9b565b90505b919050565b826108a360ff82168361311a565b60005b8160ff168160ff161015610a0c576108e686868360ff168181106108cc576108cc614924565b90506020020160208101906108e19190613f61565b61313e565b506004546001600160a01b0316631cff79cd878760ff851681811061090d5761090d614924565b90506020020160208101906109229190613f61565b63e74b981b60e01b878760ff871681811061093f5761093f614924565b90506020020160208101906109549190613f61565b6040516001600160a01b03909116602482015260440160408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b90921682526109b09291600401614992565b6000604051808303816000875af11580156109cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109f791908101906149e6565b50508080610a0490614a56565b9150506108a6565b505050505050565b610a1c612b4f565b6004546003546040516001600160a01b0392831692631cff79cd9216906305be054960e21b90610a56908990899089908990602401614a75565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b9092168252610a9c9291600401614992565b6000604051808303816000875af1158015610abb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a0c91908101906149e6565b610aeb612b4f565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b610b47612b4f565b8060005b8160ff16811015610c4f576004546001600160a01b0316631cff79cd858584818110610b7957610b79614924565b9050602002016020810190610b8e9190613f61565b600654604051636b21d69960e11b91610bad9160240190815260200190565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b9092168252610bf39291600401614992565b6000604051808303816000875af1158015610c12573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c3a91908101906149e6565b50508080610c4790614af9565b915050610b4b565b50505050565b8060005b8160ff16811015610c4f57610c798484838181106108cc576108cc614924565b506004546001600160a01b0316631cff79cd858584818110610c9d57610c9d614924565b9050602002016020810190610cb29190613f61565b6040805160048082526024820183526020820180516001600160e01b0316631fa5d41d60e11b179052915160e085901b6001600160e01b0319168152610cf9939201614992565b6000604051808303816000875af1158015610d18573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d4091908101906149e6565b50508080610d4d90614af9565b915050610c59565b610d5d612b4f565b600454600a546040516001600160a01b0392831692631cff79cd921690633843348360e01b90610a56908990899089908990602401614b12565b8060005b8160ff168160ff161015610c4f576004546001600160a01b0316631cff79cd858560ff8516818110610dcf57610dcf614924565b9050602002016020810190610de49190613f61565b6040805160048082526024820183526020820180516001600160e01b0316630390ff7560e51b179052915160e085901b6001600160e01b0319168152610e2b939201614992565b6000604051808303816000875af1158015610e4a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610e7291908101906149e6565b50508080610e7f90614a56565b915050610d9b565b600a5460405163854b89d560e01b8152600160048201526000916001600160a01b03169063854b89d590602401602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef59190614907565b610f6a57600a546040516305d7c29760e01b81523360048201526001600160a01b03909116906305d7c29790602401602060405180830381865afa158015610f41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f659190614907565b610fd8565b600a5460405163854b89d560e01b81523360048201526001600160a01b039091169063854b89d590602401602060405180830381865afa158015610fb2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd69190614907565b155b15610ff85760405163fa5cd00f60e01b8152336004820152602401610864565b61100185612d98565b60075461101c908690869086906001600160a01b03166131f2565b9050611029828683613303565b949350505050565b8060005b8160ff168160ff161015610c4f576004546001600160a01b0316631cff79cd858560ff851681811061106957611069614924565b905060200201602081019061107e9190613f61565b6040805160048082526024820183526020820180516001600160e01b03166308a5a9c960e11b179052915160e085901b6001600160e01b03191681526110c5939201614992565b6000604051808303816000875af11580156110e4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261110c91908101906149e6565b5050808061111990614a56565b915050611035565b611129612b4f565b6007546001600160a01b03168160005b8160ff168110156106dc576004546001600160a01b0316631cff79cd8463a3f8344960e01b88888681811061117057611170614924565b9050602002013560405160240161118991815260200190565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b90921682526111cf9291600401614992565b6000604051808303816000875af11580156111ee573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261121691908101906149e6565b5050808061122390614af9565b915050611139565b611233612b4f565b8060005b8160ff16811015610c4f576004546001600160a01b0316631cff79cd85858481811061126557611265614924565b905060200201602081019061127a9190613f61565b6001600160a01b03166303eadcfc6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112db9190614bc3565b6040805160048082526024820183526020820180516001600160e01b0316631fa5d41d60e11b179052915160e085901b6001600160e01b0319168152611322939201614992565b6000604051808303816000875af1158015611341573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261136991908101906149e6565b5050808061137690614af9565b915050611237565b611386612b4f565b6702c68af0bb1400008111156113b257604051630a7e67f960e21b815260048101829052602401610864565b60055460408051918252602082018390527f44e5243903d4f21681121bff9dd91691edc7fa0b9d87cc40d6d65f1755a9b1b3910160405180910390a1600555565b8261140160ff82168361311a565b60005b8160ff168160ff161015610a0c5761142a86868360ff168181106108cc576108cc614924565b506004546001600160a01b0316631cff79cd878760ff851681811061145157611451614924565b90506020020160208101906114669190613f61565b633b8abce960e01b878760ff871681811061148357611483614924565b9050602002013560405160240161149c91815260200190565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b90921682526114e29291600401614992565b6000604051808303816000875af1158015611501573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261152991908101906149e6565b5050808061153690614a56565b915050611404565b6001546001600160a01b031633146115b65760405162461bcd60e51b815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527402063616e20616363657074206f776e65727368697605c1b6064820152608401610864565b600054600154604080516001600160a01b0393841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b611630612b4f565b8261163e60ff82168361311a565b6007546001600160a01b031660005b8260ff16811015611760576004546001600160a01b0316631cff79cd83632b0408fd60e11b8a8a8681811061168457611684614924565b9050602002013589898781811061169d5761169d614924565b905060200201356040516024016116be929190918252602082015260400190565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b90921682526117049291600401614992565b6000604051808303816000875af1158015611723573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261174b91908101906149e6565b5050808061175890614af9565b91505061164d565b50505050505050565b8261177760ff82168361311a565b60005b8160ff168160ff161015610a0c576117a086868360ff168181106108cc576108cc614924565b506004546001600160a01b0316631cff79cd878760ff85168181106117c7576117c7614924565b90506020020160208101906117dc9190613f61565b634469aa7d60e11b878760ff87168181106117f9576117f9614924565b90506080020160405160240161180f9190614be0565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b90921682526118559291600401614992565b6000604051808303816000875af1158015611874573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261189c91908101906149e6565b505080806118a990614a56565b91505061177a565b8060005b8160ff16811015610c4f576118d58484838181106108cc576108cc614924565b506004546001600160a01b0316631cff79cd8585848181106118f9576118f9614924565b905060200201602081019061190e9190613f61565b6040805160048082526024820183526020820180516001600160e01b0316638456cb5960e01b179052915160e085901b6001600160e01b0319168152611955939201614992565b6000604051808303816000875af1158015611974573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261199c91908101906149e6565b505080806119a990614af9565b9150506118b5565b826119bf60ff82168361311a565b60005b8160ff168160ff161015610a0c576119e886868360ff168181106108cc576108cc614924565b506004546001600160a01b0316631cff79cd878760ff8516818110611a0f57611a0f614924565b9050602002016020810190611a249190613f61565b63bdc8144b60e01b878760ff8716818110611a4157611a41614924565b90506020020135604051602401611a5a91815260200190565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b9092168252611aa09291600401614992565b6000604051808303816000875af1158015611abf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611ae791908101906149e6565b50508080611af490614a56565b9150506119c2565b611b04612b4f565b8060005b8160ff16811015610c4f576004546001600160a01b0316631cff79cd858584818110611b3657611b36614924565b9050602002016020810190611b4b9190613f61565b6001600160a01b03166303eadcfc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bac9190614bc3565b6040805160048082526024820183526020820180516001600160e01b0316638456cb5960e01b179052915160e085901b6001600160e01b0319168152611bf3939201614992565b6000604051808303816000875af1158015611c12573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611c3a91908101906149e6565b50508080611c4790614af9565b915050611b08565b84611c5d60ff82168561311a565b611c6a60ff82168361311a565b6000805b8260ff16811015611dbc57611c8e8989838181106108cc576108cc614924565b602001516004549092506001600160a01b0316631cff79cd8363725d641f60e01b8a8a86818110611cc157611cc1614924565b9050602002016020810190611cd69190613f61565b898987818110611ce857611ce8614924565b9050602002016020810190611cfd9190613f61565b6040516001600160a01b0392831660248201529116604482015260640160408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b9092168252611d609291600401614992565b6000604051808303816000875af1158015611d7f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611da791908101906149e6565b50508080611db490614af9565b915050611c6e565b505050505050505050565b84611dd560ff82168561311a565b611de260ff82168361311a565b6000805b8260ff16811015611dbc576002546001600160a01b0316630eb9af388a8a84818110611e1457611e14614924565b9050602002016020810190611e299190613f61565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401600060405180830381865afa158015611e6d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611e959190810190614ca8565b602001519150868682818110611ead57611ead614924565b9050602002016020810190611ec29190613f61565b6001600160a01b03166323b872dd3330888886818110611ee457611ee4614924565b6040516001600160e01b031960e088901b1681526001600160a01b039586166004820152949093166024850152506020909102013560448201526064016020604051808303816000875af1158015611f40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f649190614907565b50816001600160a01b031663a77cc3b3888884818110611f8657611f86614924565b9050602002016020810190611f9b9190613f61565b878785818110611fad57611fad614924565b6040516001600160e01b031960e087901b1681526001600160a01b0390941660048501526020029190910135602483015250604401600060405180830381600087803b158015611ffc57600080fd5b505af1158015612010573d6000803e3d6000fd5b50505050808061201f90614af9565b915050611de6565b6120338251825161311a565b8151600090815b8160ff168110156106dc5760008060008060008060008a888151811061206257612062614924565b602002602001015180602001905181019061207d9190614d78565b965096509650965096509650965061209487612d98565b6120b68c89815181106120a9576120a9614924565b6020026020010151613408565b60209081015160048054604080516001600160a01b038086166024830152600019604480840191909152835180840390910181526064909201835295810180516001600160e01b031663095ea7b360e01b1790529051631cff79cd60e01b8152939e50931692631cff79cd9261212f928c929101614992565b6000604051808303816000875af115801561214e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261217691908101906149e6565b505060405163095ea7b360e01b81526001600160a01b038b81166004830152600019602483015288169063095ea7b3906044016020604051808303816000875af11580156121c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ec9190614907565b50600480546040516323b872dd60e01b815233928101929092526001600160a01b039081166024830152604482018790528816906323b872dd906064016020604051808303816000875af1158015612248573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061226c9190614907565b5060048054604080516001600160a01b038b811660248301528a81166044830152606482018a905288151560848301526001600160e01b0388811660a484015262ffffff881660c484015260e48084018890528451808503909101815261010490930184526020830180519091166321c732bd60e21b1790529151631cff79cd60e01b81529190921692631cff79cd92612308928f9201614992565b6000604051808303816000875af1158015612327573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261234f91908101906149e6565b505050505050505050808061236390614af9565b91505061203a565b612373612b4f565b6201518081111561239a57604051636a46e7e760e11b815260048101829052602401610864565b60065460408051918252602082018390527f8a8cb5791fe06275eeac010d52ee9c0c86497874dfb955d853987b17d63b1099910160405180910390a1600655565b6123e3612b4f565b8060005b8160ff16811015610c4f576004546001600160a01b0316631cff79cd85858481811061241557612415614924565b905060200201602081019061242a9190613f61565b6005546040516370897b2360e01b916124499160240190815260200190565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b909216825261248f9291600401614992565b6000604051808303816000875af11580156124ae573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124d691908101906149e6565b505080806124e390614af9565b9150506123e7565b60048054604080516379ba509760e01b815290516001600160a01b03909216926379ba509792828201926000929082900301818387803b15801561252e57600080fd5b505af1158015610c4f573d6000803e3d6000fd5b61254a612b4f565b6000828152600b602052604090205481810361257f576040516001629062fd60e01b0319815260048101839052602401610864565b60408051828152602081018490527f8a248e757d07a431570dfad8e7b8e3113b477629c38b0ff4f3dcfff3c1c298b5910160405180910390a1506000918252600b602052604090912055565b600a5460405163854b89d560e01b8152600160048201526000916001600160a01b03169063854b89d590602401602060405180830381865afa158015612615573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126399190614907565b6126ae57600a546040516305d7c29760e01b81523360048201526001600160a01b03909116906305d7c29790602401602060405180830381865afa158015612685573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126a99190614907565b61271c565b600a5460405163854b89d560e01b81523360048201526001600160a01b039091169063854b89d590602401602060405180830381865afa1580156126f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061271a9190614907565b155b1561273c5760405163fa5cd00f60e01b8152336004820152602401610864565b60075488516001600160a01b039091169061275690612d98565b60208901516001600160a01b0316158015906127eb575087511515806127eb575060085460208a015160405163016a578960e31b81526001600160a01b039182166004820152911690630b52bc4890602401602060405180830381865afa1580156127c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127e99190614907565b155b15612809576040516306b7c75960e31b815260040160405180910390fd5b87511561282d57885161281e908989846131f2565b6001600160a01b031660208a01525b61283789826134d5565b91506000861561284e5761284b8383612f9b565b90505b6128598382876135cf565b855115612888578661287e576040516306b7c75960e31b815260040160405180910390fd5b61288883876135f3565b89602001516001600160a01b0316816001600160a01b0316846001600160a01b03167f26ad9f07a47e389150a15677a365d64f42af0000b792c182ada6a3b5ab193a0b60405160405180910390a46128e5848b6000015185613303565b5050979650505050505050565b8261290060ff82168361311a565b6008546001600160a01b031660005b8260ff168160ff1610156117605761293587878360ff168181106108cc576108cc614924565b50816001600160a01b0316630b52bc4886868460ff1681811061295a5761295a614924565b905060200201602081019061296f9190613f61565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156129b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129d79190614907565b612a2a5784848260ff168181106129f0576129f0614924565b9050602002016020810190612a059190613f61565b604051631ad28c5760e11b81526001600160a01b039091166004820152602401610864565b6004546001600160a01b0316631cff79cd888860ff8516818110612a5057612a50614924565b9050602002016020810190612a659190613f61565b630a192d3960e01b888860ff8716818110612a8257612a82614924565b9050602002016020810190612a979190613f61565b6040516001600160a01b03909116602482015260440160408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b9092168252612af39291600401614992565b6000604051808303816000875af1158015612b12573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612b3a91908101906149e6565b50508080612b4790614a56565b91505061290f565b6000546001600160a01b03163314612bc15760405162461bcd60e51b815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201526e37b936903a3434b99030b1ba34b7b760891b6064820152608401610864565b565b6001600160a01b0381161580612be657506007546001600160a01b038281169116145b15612c0f5760405163e72ce82960e01b81526001600160a01b0382166004820152602401610864565b600754604080516001600160a01b03928316815291831660208301527f56fa229ccbaf666061902dae11d3700b32263d110cdaf9445834d40b6bf00c54910160405180910390a16007546001600160a01b031615612c7057612c70816136a1565b600780546001600160a01b0319166001600160a01b038316908117909155604080516311784f7d60e01b815290516311784f7d916004808201926020929091908290030181865afa158015612cc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ced9190614bc3565b600860006101000a8154816001600160a01b0302191690836001600160a01b03160217905550806001600160a01b031663a0af81f06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d759190614bc3565b600980546001600160a01b0319166001600160a01b039290921691909117905550565b600a5460405163854b89d560e01b8152600060048201526001600160a01b039091169063854b89d590602401602060405180830381865afa158015612de1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e059190614907565b612e7c57600a546040516305d7c29760e01b81526001600160a01b038381166004830152909116906305d7c29790602401602060405180830381865afa158015612e53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e779190614907565b612eec565b600a5460405163854b89d560e01b81526001600160a01b0383811660048301529091169063854b89d590602401602060405180830381865afa158015612ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eea9190614907565b155b80612f60575060085460405163016a578960e31b81526001600160a01b03838116600483015290911690630b52bc4890602401602060405180830381865afa158015612f3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f609190614907565b80612f7257506001600160a01b038116155b156106f45760405163fa5cd00f60e01b81526001600160a01b0382166004820152602401610864565b6004547f5374616b696e67000000000000000000000000000000000000000000000000006000818152600b60205260408082205460035491516001600160a01b0388811660248301529283166044820152919094166064820181905291938493631cff79cd9287927fd76fad2300000000000000000000000000000000000000000000000000000000929163c0c53b8b60e01b906084015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161307693929190602401614e14565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b90921682526130bc9291600401614992565b6000604051808303816000875af11580156130db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261310391908101906149e6565b915050808060200190518101906110299190614bc3565b80821461313a5760405163512509d360e11b815260040160405180910390fd5b5050565b613146613edf565b6002546040516301d735e760e31b81526001600160a01b03848116600483015290911690630eb9af3890602401600060405180830381865afa158015613190573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526131b89190810190614ca8565b905080604001516001600160a01b0316336001600160a01b03161461089057604051630b5024e560e11b8152336004820152602401610864565b6000806131fd613f22565b8451156132b05761320e8585613811565b600954865160405163a98a151760e01b81527f5374726174656779000000000000000000000000000000000000000000000000600482015260248101919091529193506001600160a01b03169063a98a151790604401600060405180830381865afa158015613281573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526132a99190810190614e99565b60a0015190505b6004546006546020808801516040516132f8948b946132e3948e946001600160a01b03909316938a938a92909101614f60565b60405160208183030381529060405286613898565b979650505050505050565b82156134035761331e6001600160a01b038316333086613a76565b60405163095ea7b360e01b81526001600160a01b0382811660048301526024820185905283169063095ea7b3906044016020604051808303816000875af115801561336d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133919190614907565b50604051636e553f6560e01b8152600481018490523360248201526001600160a01b03821690636e553f65906044016020604051808303816000875af11580156133df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4f9190614fdd565b505050565b613410613edf565b6002546040516301d735e760e31b81526001600160a01b03848116600483015290911690630eb9af3890602401600060405180830381865afa15801561345a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526134829190810190614ca8565b905080604001516001600160a01b0316336001600160a01b0316141580156134b557506000546001600160a01b03163314155b15610890576040516311d8f05f60e31b8152336004820152602401610864565b6004546001600160a01b0390811660a084018181527f5661756c740000000000000000000000000000000000000000000000000000006000818152600b602090815260408083205481518a5189166024820152838b015189166044820152828b015180516001600160401b039081166064840152948101518516608483015292830151841660a482015260609283015190931660c484015290890151871660e48301526080890151610104830152935190951661012486015293849392631cff79cd9287927fd76fad23000000000000000000000000000000000000000000000000000000009290632d41b1e560e11b9061014401613033565b6001600160a01b038084168252821660208201523360408201526134038382613ad0565b6040805160018082528183019092526000916020808301908036833750506040805160018082528183019092529293506000929150602082015b606081526020019060019003908161362d579050509050838260008151811061365857613658614924565b60200260200101906001600160a01b031690816001600160a01b031681525050828160008151811061368c5761368c614924565b6020026020010181905250610c4f8282612027565b60048054600754604080516001600160a01b0386811660248084019190915283518084039091018152604490920183526020820180516001600160e01b031663c30ebb1760e01b1790529151631cff79cd60e01b815293821694631cff79cd9461371094939093169201614992565b6000604051808303816000875af115801561372f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261375791908101906149e6565b5050600480546040805160206024820181905260006044808401919091528351808403909101815260649092018352810180516001600160e01b0316630cf1cfe360e01b1790529051631cff79cd60e01b81526001600160a01b0390921692631cff79cd926137ca928692909101614992565b6000604051808303816000875af11580156137e9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261340391908101906149e6565b60045482516040517f537472617465677900000000000000000000000000000000000000000000000060248201526044810191909152606060648201526000608482018190529182916001600160a01b0390911690631cff79cd9085907fd76fad23000000000000000000000000000000000000000000000000000000009060a401613076565b600454835160009182916001600160a01b0390911690631cff79cd9085907fd76fad2300000000000000000000000000000000000000000000000000000000907f4164617074657200000000000000000000000000000000000000000000000000906139048b8b613b90565b60405160240161391693929190614e14565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b909216825261395c9291600401614992565b6000604051808303816000875af115801561397b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526139a391908101906149e6565b915050808060200190518101906139ba9190614bc3565b60048054600554604080516024808201939093528151808203909301835260440181526020820180516001600160e01b03166370897b2360e01b17905251631cff79cd60e01b81529395506001600160a01b0390911692631cff79cd92613a25928792909101614992565b6000604051808303816000875af1158015613a44573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613a6c91908101906149e6565b5050509392505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052610c4f908590613c8b565b6004546002546040516001600160a01b0392831692631cff79cd92169062a6bc5f60e71b90613b03908690602401614ff6565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b9092168252613b499291600401614992565b6000604051808303816000875af1158015613b68573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c4f91908101906149e6565b600954825160405163a98a151760e01b81527f416461707465720000000000000000000000000000000000000000000000000060048201526024810191909152606091631f1ccddf60e31b9184916001600160a01b03169063a98a151790604401600060405180830381865afa158015613c0e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613c369190810190614e99565b608001518560200151604051602401613c5193929190615099565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905092915050565b6000613ce0826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613d5d9092919063ffffffff16565b8051909150156134035780806020019051810190613cfe9190614907565b6134035760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610864565b6060613d6c8484600085613d76565b90505b9392505050565b606082471015613dd75760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610864565b600080866001600160a01b03168587604051613df391906150d7565b60006040518083038185875af1925050503d8060008114613e30576040519150601f19603f3d011682016040523d82523d6000602084013e613e35565b606091505b50915091506132f88783838760608315613eb0578251600003613ea9576001600160a01b0385163b613ea95760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610864565b5081611029565b6110298383815115613ec55781518083602001fd5b8060405162461bcd60e51b815260040161086491906150f3565b6040805160e0810182526000808252602082018190529181019190915260608082015260808101613f0e613f22565b815260006020820181905260409091015290565b6040518061010001604052806008906020820280368337509192915050565b6001600160a01b03811681146106f457600080fd5b803561089081613f41565b600060208284031215613f7357600080fd5b8135613d6f81613f41565b60008083601f840112613f9057600080fd5b5081356001600160401b03811115613fa757600080fd5b6020830191508360208260051b8501011115613fc257600080fd5b9250929050565b60008060008060408587031215613fdf57600080fd5b84356001600160401b0380821115613ff657600080fd5b61400288838901613f7e565b9096509450602087013591508082111561401b57600080fd5b5061402887828801613f7e565b95989497509550505050565b6000806020838503121561404757600080fd5b82356001600160401b0381111561405d57600080fd5b61406985828601613f7e565b90969095509350505050565b6000806000806040858703121561408b57600080fd5b84356001600160401b03808211156140a257600080fd5b6140ae88838901613f7e565b909650945060208701359150808211156140c757600080fd5b818701915087601f8301126140db57600080fd5b8135818111156140ea57600080fd5b8860208260061b85010111156140ff57600080fd5b95989497505060200194505050565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b03811182821017156141465761414661410e565b60405290565b604051608081016001600160401b03811182821017156141465761414661410e565b60405160e081016001600160401b03811182821017156141465761414661410e565b60405161010081016001600160401b03811182821017156141465761414661410e565b604051601f8201601f191681016001600160401b03811182821017156141db576141db61410e565b604052919050565b60006001600160401b038211156141fc576141fc61410e565b50601f01601f191660200190565b600082601f83011261421b57600080fd5b813561422e614229826141e3565b6141b3565b81815284602083860101111561424357600080fd5b816020850160208301376000918101602001919091529392505050565b60006040828403121561427257600080fd5b604051604081016001600160401b0382821081831117156142955761429561410e565b816040528293508435835260208501359150808211156142b457600080fd5b506142c18582860161420a565b6020830152505092915050565b600080600080608085870312156142e457600080fd5b84356142ef81613f41565b935060208501356001600160401b038082111561430b57600080fd5b61431788838901614260565b9450604087013591508082111561432d57600080fd5b5061433a87828801614260565b949793965093946060013593505050565b60006020828403121561435d57600080fd5b5035919050565b6000806000806040858703121561437a57600080fd5b84356001600160401b038082111561439157600080fd5b61439d88838901613f7e565b909650945060208701359150808211156143b657600080fd5b818701915087601f8301126143ca57600080fd5b8135818111156143d957600080fd5b8860208260071b85010111156140ff57600080fd5b6000806000806000806060878903121561440757600080fd5b86356001600160401b038082111561441e57600080fd5b61442a8a838b01613f7e565b9098509650602089013591508082111561444357600080fd5b61444f8a838b01613f7e565b9096509450604089013591508082111561446857600080fd5b5061447589828a01613f7e565b979a9699509497509295939492505050565b60006001600160401b038211156144a0576144a061410e565b5060051b60200190565b600082601f8301126144bb57600080fd5b813560206144cb61422983614487565b82815260059290921b840181019181810190868411156144ea57600080fd5b8286015b848110156145295780356001600160401b0381111561450d5760008081fd5b61451b8986838b010161420a565b8452509183019183016144ee565b509695505050505050565b6000806040838503121561454757600080fd5b82356001600160401b038082111561455e57600080fd5b818501915085601f83011261457257600080fd5b8135602061458261422983614487565b82815260059290921b840181019181810190898411156145a157600080fd5b948201945b838610156145c85785356145b981613f41565b825294820194908201906145a6565b965050860135925050808211156145de57600080fd5b506145eb858286016144aa565b9150509250929050565b6000806040838503121561460857600080fd5b50508035926020909101359150565b80356001600160401b038116811461089057600080fd5b600081830361012081121561464257600080fd5b61464a614124565b9150823561465781613f41565b8252602083013561466781613f41565b60208301526080603f198201121561467e57600080fd5b5061468761414c565b61469360408401614617565b81526146a160608401614617565b60208201526146b260808401614617565b60408201526146c360a08401614617565b606082015260408201526146d960c08301613f56565b606082015260e082013560808201526146f56101008301613f56565b60a082015292915050565b80151581146106f457600080fd5b803561089081614700565b600082601f83011261472a57600080fd5b614732614190565b8061010084018581111561474557600080fd5b845b8181101561476857803561475a81613f41565b845260209384019301614747565b509095945050505050565b60006101c0828403121561478657600080fd5b61478e61416e565b905061479982613f56565b81526147a760208301613f56565b60208201526147b860408301613f56565b604082015260608201356001600160401b038111156147d657600080fd5b6147e28482850161420a565b6060830152506147f58360808401614719565b60808201526148076101808301613f56565b60a08201526101a082013560c082015292915050565b60008060008060008060006101e0888a03121561483957600080fd5b614843898961462e565b96506101208801356001600160401b038082111561486057600080fd5b61486c8b838c01614260565b97506101408a013591508082111561488357600080fd5b61488f8b838c01614260565b965061489e6101608b0161470e565b95506101808a01359150808211156148b557600080fd5b6148c18b838c0161420a565b94506101a08a01359150808211156148d857600080fd5b506148e58a828b01614773565b9250506101c0880135905092959891949750929550565b805161089081614700565b60006020828403121561491957600080fd5b8151613d6f81614700565b634e487b7160e01b600052603260045260246000fd5b60005b8381101561495557818101518382015260200161493d565b83811115610c4f5750506000910152565b6000815180845261497e81602086016020860161493a565b601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201819052600090613d6c90830184614966565b60006149c4614229846141e3565b90508281528383830111156149d857600080fd5b613d6f83602083018461493a565b600080604083850312156149f957600080fd5b8251614a0481614700565b60208401519092506001600160401b03811115614a2057600080fd5b8301601f81018513614a3157600080fd5b6145eb858251602084016149b6565b634e487b7160e01b600052601160045260246000fd5b600060ff821660ff8103614a6c57614a6c614a40565b60010192915050565b6040808252810184905260008560608301825b87811015614ab8578235614a9b81613f41565b6001600160a01b0316825260209283019290910190600101614a88565b5083810360208501528481526001600160fb1b03851115614ad857600080fd5b8460051b915081866020830137600091016020019081529695505050505050565b600060018201614b0b57614b0b614a40565b5060010190565b60408082528181018590526000908660608401835b88811015614b57578235614b3a81613f41565b6001600160a01b0316825260209283019290910190600101614b27565b5084810360208681019190915286825291508690820160005b87811015614baa578235614b8381614700565b1515825282840135614b9481614700565b1515828501529184019190840190600101614b70565b509998505050505050505050565b805161089081613f41565b600060208284031215614bd557600080fd5b8151613d6f81613f41565b608081016001600160401b0380614bf685614617565b16835280614c0660208601614617565b16602084015280614c1960408601614617565b16604084015280614c2c60608601614617565b1660608401525092915050565b600082601f830112614c4a57600080fd5b613d6f838351602085016149b6565b600082601f830112614c6a57600080fd5b614c72614190565b80610100840185811115614c8557600080fd5b845b81811015614768578051614c9a81613f41565b845260209384019301614c87565b600060208284031215614cba57600080fd5b81516001600160401b0380821115614cd157600080fd5b908301906101c08286031215614ce657600080fd5b614cee61416e565b614cf783614bb8565b8152614d0560208401614bb8565b6020820152614d1660408401614bb8565b6040820152606083015182811115614d2d57600080fd5b614d3987828601614c39565b606083015250614d4c8660808501614c59565b6080820152614d5e6101808401614bb8565b60a08201526101a0929092015160c0830152509392505050565b600080600080600080600060e0888a031215614d9357600080fd5b8751614d9e81613f41565b6020890151909750614daf81613f41565b604089015160608a01519197509550614dc781614700565b60808901519094506001600160e01b0381168114614de457600080fd5b60a089015190935062ffffff81168114614dfd57600080fd5b8092505060c0880151905092959891949750929550565b838152826020820152606060408201526000614e336060830184614966565b95945050505050565b600082601f830112614e4d57600080fd5b614e55614190565b80610100840185811115614e6857600080fd5b845b818110156147685780516001600160e01b031981168114614e8b5760008081fd5b845260209384019301614e6a565b600060208284031215614eab57600080fd5b81516001600160401b0380821115614ec257600080fd5b908301906101a08286031215614ed757600080fd5b614edf614124565b8251614eea81613f41565b81526020830151614efa81614700565b6020820152604083015182811115614f1157600080fd5b614f1d87828601614c39565b604083015250614f2f606084016148fc565b6060820152614f4060808401614bb8565b6080820152614f528660a08501614e3c565b60a082015295945050505050565b60006101a060018060a01b03808a1684526020818a168186015281891660408601528760608601526080850191508660005b6008811015614fb95781516001600160e01b03191684529282019290820190600101614f92565b5050505080610180840152614fd081840185614966565b9998505050505050505050565b600060208284031215614fef57600080fd5b5051919050565b6000602080835260018060a01b038085511682850152808286015116604085015280604086015116606085015260608501516101c080608087015261503f6101e0870183614966565b9150608087015160a0870160005b600881101561506c57825186168252918601919086019060010161504d565b50505060a08701516001600160a01b03166101a087015260c0909601519590940194909452509092915050565b6060815260006150ac6060830186614966565b6001600160a01b038516602084015282810360408401526150cd8185614966565b9695505050505050565b600082516150e981846020870161493a565b9190910192915050565b602081526000613d6f602083018461496656fea2646970667358221220ac0d0f4777d8573437831a50ca9370208ad9901e63f7b1383acc8aa770066cba64736f6c634300080f0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000022f5413c075ccd56d575a54763831c4c27a37bdb000000000000000000000000564fbe59c448743fa9382e691a0320458f6dcde5000000000000000000000000a8c5815f6ea5f7a1551541b0d7f970d546126bdb000000000000000000000000007318dc89b314b47609c684260cfbfbcd4128640000000000000000000000007a33b5b57c8b235a3519e6c010027c5cebb15cb4000000000000000000000000f76b7de04a76609766f437d2eb6021748c0598af
-----Decoded View---------------
Arg [0] : _owner (address): 0x22f5413C075Ccd56D575A54763831C4c27A37Bdb
Arg [1] : _adminProxy (address): 0x564fBe59c448743FA9382E691a0320458F6dCDE5
Arg [2] : _deploymentController (address): 0xa8C5815f6Ea5F7A1551541B0d7F970D546126bDB
Arg [3] : _vaultRegistry (address): 0x007318Dc89B314b47609C684260CfbfbcD412864
Arg [4] : _permissionRegistry (address): 0x7a33b5b57C8b235A3519e6C010027c5cebB15CB4
Arg [5] : _escrow (address): 0xF76B7dE04a76609766f437D2Eb6021748C0598Af
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 00000000000000000000000022f5413c075ccd56d575a54763831c4c27a37bdb
Arg [1] : 000000000000000000000000564fbe59c448743fa9382e691a0320458f6dcde5
Arg [2] : 000000000000000000000000a8c5815f6ea5f7a1551541b0d7f970d546126bdb
Arg [3] : 000000000000000000000000007318dc89b314b47609c684260cfbfbcd412864
Arg [4] : 0000000000000000000000007a33b5b57c8b235a3519e6c010027c5cebb15cb4
Arg [5] : 000000000000000000000000f76b7de04a76609766f437d2eb6021748c0598af
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
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.