Overview
ETH Balance
ETH Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 28473367 | 2 hrs ago | 0 ETH | ||||
| 28466522 | 7 hrs ago | 0 ETH | ||||
| 28465548 | 8 hrs ago | 0 ETH | ||||
| 28464567 | 8 hrs ago | 0 ETH | ||||
| 28459956 | 12 hrs ago | 0 ETH | ||||
| 28451215 | 18 hrs ago | 0 ETH | ||||
| 28433591 | 31 hrs ago | 0 ETH | ||||
| 28423650 | 39 hrs ago | 0 ETH | ||||
| 28416801 | 44 hrs ago | 0 ETH | ||||
| 28349960 | 3 days ago | 0 ETH | ||||
| 28257891 | 6 days ago | 0 ETH | ||||
| 28052834 | 11 days ago | 0 ETH | ||||
| 27908837 | 14 days ago | 0 ETH | ||||
| 27908814 | 14 days ago | 0 ETH | ||||
| 27908814 | 14 days ago | 0 ETH | ||||
| 27908814 | 14 days ago | 0 ETH | ||||
| 27884703 | 15 days ago | 0 ETH | ||||
| 27732841 | 18 days ago | 0 ETH | ||||
| 27732585 | 18 days ago | 0 ETH | ||||
| 27577037 | 22 days ago | 0 ETH | ||||
| 27447829 | 25 days ago | 0 ETH | ||||
| 27447809 | 25 days ago | 0 ETH | ||||
| 27447809 | 25 days ago | 0 ETH | ||||
| 27447809 | 25 days ago | 0 ETH | ||||
| 27384228 | 27 days ago | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0xB2f32B62...41ea52991 The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
ERC4626Form
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;
import { ERC4626FormImplementation } from "src/forms/ERC4626FormImplementation.sol";
import { BaseForm } from "src/BaseForm.sol";
import { InitSingleVaultData } from "src/types/DataTypes.sol";
/// @title ERC4626Form
/// @dev The Form implementation for normal ERC4626 vaults
/// @author Zeropoint Labs
contract ERC4626Form is ERC4626FormImplementation {
//////////////////////////////////////////////////////////////
// CONSTANTS //
//////////////////////////////////////////////////////////////
uint8 constant stateRegistryId = 1; // CoreStateRegistry
//////////////////////////////////////////////////////////////
// CONSTRUCTOR //
//////////////////////////////////////////////////////////////
constructor(address superRegistry_) ERC4626FormImplementation(superRegistry_, stateRegistryId) { }
//////////////////////////////////////////////////////////////
// INTERNAL FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @inheritdoc BaseForm
function _directDepositIntoVault(
InitSingleVaultData memory singleVaultData_,
address /*srcSender_*/
)
internal
override
returns (uint256 shares)
{
shares = _processDirectDeposit(singleVaultData_);
}
/// @inheritdoc BaseForm
function _xChainDepositIntoVault(
InitSingleVaultData memory singleVaultData_,
address, /*srcSender_*/
uint64 srcChainId_
)
internal
override
returns (uint256 shares)
{
shares = _processXChainDeposit(singleVaultData_, srcChainId_);
}
/// @inheritdoc BaseForm
function _directWithdrawFromVault(
InitSingleVaultData memory singleVaultData_,
address /*srcSender_*/
)
internal
override
returns (uint256 assets)
{
assets = _processDirectWithdraw(singleVaultData_);
}
/// @inheritdoc BaseForm
function _xChainWithdrawFromVault(
InitSingleVaultData memory singleVaultData_,
address, /*srcSender_*/
uint64 srcChainId_
)
internal
override
returns (uint256 assets)
{
assets = _processXChainWithdraw(singleVaultData_, srcChainId_);
}
/// @inheritdoc BaseForm
function _emergencyWithdraw(address receiverAddress_, uint256 amount_) internal override {
_processEmergencyWithdraw(receiverAddress_, amount_);
}
/// @inheritdoc BaseForm
function _forwardDustToPaymaster(address token_) internal override {
_processForwardDustToPaymaster(token_);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;
import { BaseForm } from "src/BaseForm.sol";
import { LiquidityHandler } from "src/crosschain-liquidity/LiquidityHandler.sol";
import { IBridgeValidator } from "src/interfaces/IBridgeValidator.sol";
import { Error } from "src/libraries/Error.sol";
import { DataLib } from "src/libraries/DataLib.sol";
import { InitSingleVaultData } from "src/types/DataTypes.sol";
import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol";
import { IERC20Metadata } from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
import { IERC4626 } from "openzeppelin-contracts/contracts/interfaces/IERC4626.sol";
/// @title ERC4626FormImplementation
/// @dev Has common ERC4626 internal functions that can be re-used by implementations
/// @author Zeropoint Labs
abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler {
using SafeERC20 for IERC20;
using SafeERC20 for IERC4626;
using DataLib for uint256;
//////////////////////////////////////////////////////////////
// CONSTANTS //
//////////////////////////////////////////////////////////////
uint8 internal immutable STATE_REGISTRY_ID;
uint256 internal constant ENTIRE_SLIPPAGE = 10_000;
//////////////////////////////////////////////////////////////
// STRUCTS //
//////////////////////////////////////////////////////////////
struct DirectDepositLocalVars {
uint64 chainId;
address asset;
address bridgeValidator;
uint256 shares;
uint256 balanceBefore;
uint256 assetDifference;
uint256 nonce;
uint256 deadline;
uint256 inputAmount;
bytes signature;
}
struct DirectWithdrawLocalVars {
uint64 chainId;
address asset;
address bridgeValidator;
uint256 amount;
}
struct XChainWithdrawLocalVars {
uint64 dstChainId;
address asset;
address bridgeValidator;
uint256 balanceBefore;
uint256 balanceAfter;
uint256 amount;
}
//////////////////////////////////////////////////////////////
// CONSTRUCTOR //
//////////////////////////////////////////////////////////////
constructor(address superRegistry_, uint8 stateRegistryId_) BaseForm(superRegistry_) {
/// @dev check if state registry id is valid
superRegistry.getStateRegistry(stateRegistryId_);
STATE_REGISTRY_ID = stateRegistryId_;
}
//////////////////////////////////////////////////////////////
// EXTERNAL VIEW FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @inheritdoc BaseForm
function getVaultName() public view virtual override returns (string memory) {
return IERC4626(vault).name();
}
/// @inheritdoc BaseForm
function getVaultSymbol() public view virtual override returns (string memory) {
return IERC4626(vault).symbol();
}
/// @inheritdoc BaseForm
function getVaultDecimals() public view virtual override returns (uint256) {
return uint256(IERC4626(vault).decimals());
}
/// @inheritdoc BaseForm
function getPricePerVaultShare() public view virtual override returns (uint256) {
uint256 vaultDecimals = IERC4626(vault).decimals();
return IERC4626(vault).convertToAssets(10 ** vaultDecimals);
}
/// @inheritdoc BaseForm
function getVaultShareBalance() public view virtual override returns (uint256) {
return IERC4626(vault).balanceOf(address(this));
}
/// @inheritdoc BaseForm
function getTotalAssets() public view virtual override returns (uint256) {
return IERC4626(vault).totalAssets();
}
/// @inheritdoc BaseForm
function getTotalSupply() public view virtual override returns (uint256) {
return IERC4626(vault).totalSupply();
}
/// @inheritdoc BaseForm
function getPreviewPricePerVaultShare() public view virtual override returns (uint256) {
uint256 vaultDecimals = IERC4626(vault).decimals();
return IERC4626(vault).previewRedeem(10 ** vaultDecimals);
}
/// @inheritdoc BaseForm
function previewDepositTo(uint256 assets_) public view virtual override returns (uint256) {
return IERC4626(vault).convertToShares(assets_);
}
/// @inheritdoc BaseForm
function previewWithdrawFrom(uint256 assets_) public view virtual override returns (uint256) {
return IERC4626(vault).previewWithdraw(assets_);
}
/// @inheritdoc BaseForm
function previewRedeemFrom(uint256 shares_) public view virtual override returns (uint256) {
return IERC4626(vault).previewRedeem(shares_);
}
/// @inheritdoc BaseForm
function superformYieldTokenName() external view virtual override returns (string memory) {
return string(abi.encodePacked(IERC20Metadata(vault).name(), " SuperPosition"));
}
/// @inheritdoc BaseForm
function superformYieldTokenSymbol() external view virtual override returns (string memory) {
return string(abi.encodePacked("sp-", IERC20Metadata(vault).symbol()));
}
/// @inheritdoc BaseForm
function getStateRegistryId() external view override returns (uint8) {
return STATE_REGISTRY_ID;
}
//////////////////////////////////////////////////////////////
// INTERNAL FUNCTIONS //
//////////////////////////////////////////////////////////////
function _processDirectDeposit(InitSingleVaultData memory singleVaultData_) internal returns (uint256 shares) {
DirectDepositLocalVars memory vars;
IERC4626 v = IERC4626(vault);
vars.asset = address(asset);
vars.balanceBefore = IERC20(vars.asset).balanceOf(address(this));
IERC20 token = IERC20(singleVaultData_.liqData.token);
if (address(token) != NATIVE && singleVaultData_.liqData.txData.length == 0) {
/// @dev this is only valid if token == asset (no txData)
if (singleVaultData_.liqData.token != vars.asset) revert Error.DIFFERENT_TOKENS();
/// @dev handles the asset token transfers.
if (token.allowance(msg.sender, address(this)) < singleVaultData_.amount) {
revert Error.INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT();
}
/// @dev transfers input token, which is the same as vault asset, to the form
token.safeTransferFrom(msg.sender, address(this), singleVaultData_.amount);
}
/// @dev non empty txData means there is a swap needed before depositing (input asset not the same as vault
/// asset)
if (singleVaultData_.liqData.txData.length != 0) {
vars.bridgeValidator = superRegistry.getBridgeValidator(singleVaultData_.liqData.bridgeId);
vars.chainId = CHAIN_ID;
vars.inputAmount =
IBridgeValidator(vars.bridgeValidator).decodeAmountIn(singleVaultData_.liqData.txData, false);
if (address(token) != NATIVE) {
/// @dev checks the allowance before transfer from router
if (token.allowance(msg.sender, address(this)) < vars.inputAmount) {
revert Error.INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT();
}
/// @dev transfers input token, which is different from the vault asset, to the form
token.safeTransferFrom(msg.sender, address(this), vars.inputAmount);
}
IBridgeValidator(vars.bridgeValidator).validateTxData(
IBridgeValidator.ValidateTxDataArgs(
singleVaultData_.liqData.txData,
vars.chainId,
vars.chainId,
vars.chainId,
true,
address(this),
msg.sender,
address(token),
address(0)
)
);
_dispatchTokens(
superRegistry.getBridgeAddress(singleVaultData_.liqData.bridgeId),
singleVaultData_.liqData.txData,
address(token),
vars.inputAmount,
singleVaultData_.liqData.nativeAmount
);
if (
IBridgeValidator(vars.bridgeValidator).decodeSwapOutputToken(singleVaultData_.liqData.txData)
!= vars.asset
) {
revert Error.DIFFERENT_TOKENS();
}
}
vars.assetDifference = IERC20(vars.asset).balanceOf(address(this)) - vars.balanceBefore;
/// @dev the difference in vault tokens, ready to be deposited, is compared with the amount inscribed in the
/// superform data
if (
vars.assetDifference * ENTIRE_SLIPPAGE
< singleVaultData_.amount * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)
) {
revert Error.DIRECT_DEPOSIT_SWAP_FAILED();
}
/// @dev notice that vars.assetDifference is deposited regardless if txData exists or not
/// @dev this presumes no dust is left in the superform
IERC20(vars.asset).safeIncreaseAllowance(vault, vars.assetDifference);
/// @dev deposit assets for shares and add extra validation check to ensure intended ERC4626 behavior
shares = _depositAndValidate(singleVaultData_, v, vars.assetDifference);
}
function _processXChainDeposit(
InitSingleVaultData memory singleVaultData_,
uint64 srcChainId_
)
internal
returns (uint256 shares)
{
(,, uint64 dstChainId) = singleVaultData_.superformId.getSuperform();
address vaultLoc = vault;
IERC4626 v = IERC4626(vaultLoc);
if (IERC20(asset).allowance(msg.sender, address(this)) < singleVaultData_.amount) {
revert Error.INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT();
}
/// @dev pulling from sender, to auto-send tokens back in case of failed deposits / reverts
IERC20(asset).safeTransferFrom(msg.sender, address(this), singleVaultData_.amount);
/// @dev allowance is modified inside of the IERC20.transferFrom() call
IERC20(asset).safeIncreaseAllowance(vaultLoc, singleVaultData_.amount);
/// @dev deposit assets for shares and add extra validation check to ensure intended ERC4626 behavior
shares = _depositAndValidate(singleVaultData_, v, singleVaultData_.amount);
emit Processed(srcChainId_, dstChainId, singleVaultData_.payloadId, singleVaultData_.amount, vaultLoc);
}
function _processDirectWithdraw(InitSingleVaultData memory singleVaultData_) internal returns (uint256 assets) {
DirectWithdrawLocalVars memory vars;
/// @dev if there is no txData, on withdraws the receiver is receiverAddress, otherwise it
/// is this contract (before swap)
IERC4626 v = IERC4626(vault);
IERC20 a = IERC20(asset);
if (!singleVaultData_.retain4626) {
vars.asset = address(asset);
/// @dev redeem shares for assets and add extra validation check to ensure intended ERC4626 behavior
assets = _withdrawAndValidate(singleVaultData_, v, a);
if (singleVaultData_.liqData.txData.length != 0) {
vars.bridgeValidator = superRegistry.getBridgeValidator(singleVaultData_.liqData.bridgeId);
vars.amount =
IBridgeValidator(vars.bridgeValidator).decodeAmountIn(singleVaultData_.liqData.txData, false);
/// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault
/// @dev if less it should be within the slippage limit specified by the user
/// @dev important to maintain so that the keeper cannot update with malicious data after successful
/// withdraw
if (_isWithdrawTxDataAmountInvalid(vars.amount, assets, singleVaultData_.maxSlippage)) {
revert Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST();
}
vars.chainId = CHAIN_ID;
/// @dev validate and perform the swap to desired output token and send to beneficiary
IBridgeValidator(vars.bridgeValidator).validateTxData(
IBridgeValidator.ValidateTxDataArgs(
singleVaultData_.liqData.txData,
vars.chainId,
vars.chainId,
singleVaultData_.liqData.liqDstChainId,
false,
address(this),
singleVaultData_.receiverAddress,
vars.asset,
address(0)
)
);
_dispatchTokens(
superRegistry.getBridgeAddress(singleVaultData_.liqData.bridgeId),
singleVaultData_.liqData.txData,
vars.asset,
vars.amount,
singleVaultData_.liqData.nativeAmount
);
}
} else {
/// @dev transfer shares to user and do not redeem shares for assets
v.safeTransfer(singleVaultData_.receiverAddress, singleVaultData_.amount);
return 0;
}
}
function _processXChainWithdraw(
InitSingleVaultData memory singleVaultData_,
uint64 srcChainId_
)
internal
returns (uint256 assets)
{
XChainWithdrawLocalVars memory vars;
uint256 len = singleVaultData_.liqData.txData.length;
/// @dev a case where the withdraw req liqData has a valid token and tx data is not updated by the keeper
if (singleVaultData_.liqData.token != address(0) && len == 0) {
revert Error.WITHDRAW_TX_DATA_NOT_UPDATED();
} else if (singleVaultData_.liqData.token == address(0) && len != 0) {
revert Error.WITHDRAW_TOKEN_NOT_UPDATED();
}
(,, vars.dstChainId) = singleVaultData_.superformId.getSuperform();
IERC4626 v = IERC4626(vault);
IERC20 a = IERC20(asset);
if (!singleVaultData_.retain4626) {
vars.asset = address(asset);
/// @dev redeem shares for assets and add extra validation check to ensure intended ERC4626 behavior
assets = _withdrawAndValidate(singleVaultData_, v, a);
if (len != 0) {
vars.bridgeValidator = superRegistry.getBridgeValidator(singleVaultData_.liqData.bridgeId);
vars.amount =
IBridgeValidator(vars.bridgeValidator).decodeAmountIn(singleVaultData_.liqData.txData, false);
/// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault
/// @dev if less it should be within the slippage limit specified by the user
/// @dev important to maintain so that the keeper cannot update with malicious data after successful
/// withdraw
if (_isWithdrawTxDataAmountInvalid(vars.amount, assets, singleVaultData_.maxSlippage)) {
revert Error.XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST();
}
/// @dev validate and perform the swap to desired output token and send to beneficiary
IBridgeValidator(vars.bridgeValidator).validateTxData(
IBridgeValidator.ValidateTxDataArgs(
singleVaultData_.liqData.txData,
vars.dstChainId,
srcChainId_,
singleVaultData_.liqData.liqDstChainId,
false,
address(this),
singleVaultData_.receiverAddress,
vars.asset,
address(0)
)
);
_dispatchTokens(
superRegistry.getBridgeAddress(singleVaultData_.liqData.bridgeId),
singleVaultData_.liqData.txData,
vars.asset,
vars.amount,
singleVaultData_.liqData.nativeAmount
);
}
} else {
/// @dev transfer shares to user and do not redeem shares for assets
v.safeTransfer(singleVaultData_.receiverAddress, singleVaultData_.amount);
return 0;
}
emit Processed(srcChainId_, vars.dstChainId, singleVaultData_.payloadId, singleVaultData_.amount, vault);
}
function _depositAndValidate(
InitSingleVaultData memory singleVaultData_,
IERC4626 v,
uint256 assetDifference
)
internal
returns (uint256 shares)
{
address sharesReceiver = singleVaultData_.retain4626 ? singleVaultData_.receiverAddress : address(this);
uint256 sharesBalanceBefore = v.balanceOf(sharesReceiver);
shares = v.deposit(assetDifference, sharesReceiver);
uint256 sharesBalanceAfter = v.balanceOf(sharesReceiver);
if (
(sharesBalanceAfter - sharesBalanceBefore != shares)
|| (
ENTIRE_SLIPPAGE * shares
< ((singleVaultData_.outputAmount * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)))
)
) {
revert Error.VAULT_IMPLEMENTATION_FAILED();
}
}
function _withdrawAndValidate(
InitSingleVaultData memory singleVaultData_,
IERC4626 v,
IERC20 a
)
internal
returns (uint256 assets)
{
address assetsReceiver =
singleVaultData_.liqData.txData.length == 0 ? singleVaultData_.receiverAddress : address(this);
uint256 assetsBalanceBefore = a.balanceOf(assetsReceiver);
assets = v.redeem(singleVaultData_.amount, assetsReceiver, address(this));
uint256 assetsBalanceAfter = a.balanceOf(assetsReceiver);
if (
(assetsBalanceAfter - assetsBalanceBefore != assets)
|| (
ENTIRE_SLIPPAGE * assets
< ((singleVaultData_.outputAmount * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)))
)
) {
revert Error.VAULT_IMPLEMENTATION_FAILED();
}
if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL();
}
function _isWithdrawTxDataAmountInvalid(
uint256 bridgeDecodedAmount_,
uint256 redeemedAmount_,
uint256 slippage_
)
internal
pure
returns (bool isInvalid)
{
if (
bridgeDecodedAmount_ > redeemedAmount_
|| ((bridgeDecodedAmount_ * ENTIRE_SLIPPAGE) < (redeemedAmount_ * (ENTIRE_SLIPPAGE - slippage_)))
) return true;
}
function _processEmergencyWithdraw(address receiverAddress_, uint256 amount_) internal {
IERC4626 v = IERC4626(vault);
if (receiverAddress_ == address(0)) revert Error.ZERO_ADDRESS();
if (v.balanceOf(address(this)) < amount_) {
revert Error.INSUFFICIENT_BALANCE();
}
v.safeTransfer(receiverAddress_, amount_);
emit EmergencyWithdrawalProcessed(receiverAddress_, amount_);
}
function _processForwardDustToPaymaster(address token_) internal {
if (token_ == address(0)) revert Error.ZERO_ADDRESS();
address paymaster = superRegistry.getAddress(keccak256("PAYMASTER"));
IERC20 token = IERC20(token_);
uint256 dust = token.balanceOf(address(this));
if (dust != 0) {
token.safeTransfer(paymaster, dust);
emit FormDustForwardedToPaymaster(token_, dust);
}
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;
import { IBaseForm } from "src/interfaces/IBaseForm.sol";
import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol";
import { ISuperformFactory } from "src/interfaces/ISuperformFactory.sol";
import { IEmergencyQueue } from "src/interfaces/IEmergencyQueue.sol";
import { DataLib } from "src/libraries/DataLib.sol";
import { Error } from "src/libraries/Error.sol";
import { InitSingleVaultData } from "src/types/DataTypes.sol";
import { Initializable } from "openzeppelin-contracts/contracts/proxy/utils/Initializable.sol";
import { ERC165 } from "openzeppelin-contracts/contracts/utils/introspection/ERC165.sol";
import { IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol";
/// @title BaseForm
/// @dev Abstract contract to be inherited by different Form implementations
/// @author Zeropoint Labs
abstract contract BaseForm is IBaseForm, Initializable, ERC165 {
using DataLib for uint256;
//////////////////////////////////////////////////////////////
// CONSTANTS //
//////////////////////////////////////////////////////////////
ISuperRegistry public immutable superRegistry;
uint64 public immutable CHAIN_ID;
//////////////////////////////////////////////////////////////
// STATE VARIABLES //
//////////////////////////////////////////////////////////////
/// @dev the address of the vault that was added
address public vault;
/// @dev underlying asset of vault this form pertains to
address public asset;
//////////////////////////////////////////////////////////////
// MODIFIERS //
//////////////////////////////////////////////////////////////
modifier notPaused(InitSingleVaultData memory singleVaultData_) {
if (
!ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))).isSuperform(
singleVaultData_.superformId
)
) {
revert Error.SUPERFORM_ID_NONEXISTENT();
}
(, uint32 formImplementationId_,) = singleVaultData_.superformId.getSuperform();
if (
ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))).isFormImplementationPaused(
formImplementationId_
)
) revert Error.PAUSED();
_;
}
modifier onlySuperRouter() {
if (superRegistry.getAddress(keccak256("SUPERFORM_ROUTER")) != msg.sender) revert Error.NOT_SUPERFORM_ROUTER();
_;
}
modifier onlyCoreStateRegistry() {
if (superRegistry.getAddress(keccak256("CORE_STATE_REGISTRY")) != msg.sender) {
revert Error.NOT_CORE_STATE_REGISTRY();
}
_;
}
modifier onlyEmergencyQueue() {
if (msg.sender != superRegistry.getAddress(keccak256("EMERGENCY_QUEUE"))) {
revert Error.NOT_EMERGENCY_QUEUE();
}
_;
}
//////////////////////////////////////////////////////////////
// CONSTRUCTOR //
//////////////////////////////////////////////////////////////
constructor(address superRegistry_) {
if (superRegistry_ == address(0)) {
revert Error.ZERO_ADDRESS();
}
if (block.chainid > type(uint64).max) {
revert Error.BLOCK_CHAIN_ID_OUT_OF_BOUNDS();
}
CHAIN_ID = uint64(block.chainid);
superRegistry = ISuperRegistry(superRegistry_);
_disableInitializers();
}
//////////////////////////////////////////////////////////////
// EXTERNAL VIEW FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @inheritdoc IBaseForm
function superformYieldTokenName() external view virtual override returns (string memory);
/// @inheritdoc IBaseForm
function superformYieldTokenSymbol() external view virtual override returns (string memory);
/// @inheritdoc IBaseForm
function getStateRegistryId() external view virtual override returns (uint8);
// @inheritdoc IBaseForm
function getVaultAddress() external view override returns (address) {
return vault;
}
// @inheritdoc IBaseForm
function getVaultAsset() public view override returns (address) {
return asset;
}
/// @inheritdoc IBaseForm
function getVaultName() public view virtual override returns (string memory);
/// @inheritdoc IBaseForm
function getVaultSymbol() public view virtual override returns (string memory);
/// @inheritdoc IBaseForm
function getVaultDecimals() public view virtual override returns (uint256);
/// @inheritdoc IBaseForm
function getPricePerVaultShare() public view virtual override returns (uint256);
/// @inheritdoc IBaseForm
function getVaultShareBalance() public view virtual override returns (uint256);
/// @inheritdoc IBaseForm
function getTotalAssets() public view virtual override returns (uint256);
/// @inheritdoc IBaseForm
function getTotalSupply() public view virtual override returns (uint256);
// @inheritdoc IBaseForm
function getPreviewPricePerVaultShare() public view virtual override returns (uint256);
/// @inheritdoc IBaseForm
function previewDepositTo(uint256 assets_) public view virtual override returns (uint256);
/// @inheritdoc IBaseForm
function previewWithdrawFrom(uint256 assets_) public view virtual override returns (uint256);
/// @inheritdoc IBaseForm
function previewRedeemFrom(uint256 shares_) public view virtual override returns (uint256);
//////////////////////////////////////////////////////////////
// EXTERNAL WRITE FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @param superRegistry_ ISuperRegistry address deployed
/// @param vault_ The vault address this form pertains to
/// @param asset_ The underlying asset address of the vault this form pertains to
function initialize(address superRegistry_, address vault_, address asset_) external initializer {
if (ISuperRegistry(superRegistry_) != superRegistry) revert Error.NOT_SUPER_REGISTRY();
if (vault_ == address(0) || asset_ == address(0)) revert Error.ZERO_ADDRESS();
vault = vault_;
asset = asset_;
}
/// @inheritdoc IBaseForm
function directDepositIntoVault(
InitSingleVaultData memory singleVaultData_,
address srcSender_
)
external
payable
override
onlySuperRouter
notPaused(singleVaultData_)
returns (uint256 shares)
{
shares = _directDepositIntoVault(singleVaultData_, srcSender_);
}
/// @inheritdoc IBaseForm
function directWithdrawFromVault(
InitSingleVaultData memory singleVaultData_,
address srcSender_
)
external
override
onlySuperRouter
returns (uint256 assets)
{
if (!_isPaused(singleVaultData_.superformId)) {
assets = _directWithdrawFromVault(singleVaultData_, srcSender_);
} else {
IEmergencyQueue(superRegistry.getAddress(keccak256("EMERGENCY_QUEUE"))).queueWithdrawal(singleVaultData_);
}
}
/// @inheritdoc IBaseForm
function xChainDepositIntoVault(
InitSingleVaultData memory singleVaultData_,
address srcSender_,
uint64 srcChainId_
)
external
override
onlyCoreStateRegistry
notPaused(singleVaultData_)
returns (uint256 shares)
{
if (srcChainId_ != 0 && srcChainId_ != CHAIN_ID) {
shares = _xChainDepositIntoVault(singleVaultData_, srcSender_, srcChainId_);
} else {
revert Error.INVALID_CHAIN_ID();
}
}
/// @inheritdoc IBaseForm
function xChainWithdrawFromVault(
InitSingleVaultData memory singleVaultData_,
address srcSender_,
uint64 srcChainId_
)
external
override
onlyCoreStateRegistry
returns (uint256 assets)
{
if (srcChainId_ != 0 && srcChainId_ != CHAIN_ID) {
if (!_isPaused(singleVaultData_.superformId)) {
assets = _xChainWithdrawFromVault(singleVaultData_, srcSender_, srcChainId_);
} else {
IEmergencyQueue(superRegistry.getAddress(keccak256("EMERGENCY_QUEUE"))).queueWithdrawal(
singleVaultData_
);
}
} else {
revert Error.INVALID_CHAIN_ID();
}
}
/// @inheritdoc IBaseForm
function emergencyWithdraw(address receiverAddress_, uint256 amount_) external override onlyEmergencyQueue {
_emergencyWithdraw(receiverAddress_, amount_);
}
/// @inheritdoc IBaseForm
function forwardDustToPaymaster(address token_) external override {
if (token_ == vault) revert Error.CANNOT_FORWARD_4646_TOKEN();
_forwardDustToPaymaster(token_);
}
/// @dev Checks if the Form implementation has the appropriate interface support
/// @param interfaceId_ is the interfaceId to check
function supportsInterface(bytes4 interfaceId_) public view virtual override(ERC165, IERC165) returns (bool) {
return interfaceId_ == type(IBaseForm).interfaceId || super.supportsInterface(interfaceId_);
}
//////////////////////////////////////////////////////////////
// INTERNAL FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @dev Deposits underlying tokens into a vault
function _directDepositIntoVault(
InitSingleVaultData memory singleVaultData_,
address srcSender_
)
internal
virtual
returns (uint256 shares);
/// @dev Deposits underlying tokens into a vault
function _xChainDepositIntoVault(
InitSingleVaultData memory singleVaultData_,
address srcSender_,
uint64 srcChainId_
)
internal
virtual
returns (uint256 shares);
/// @dev Withdraws underlying tokens from a vault
function _directWithdrawFromVault(
InitSingleVaultData memory singleVaultData_,
address srcSender_
)
internal
virtual
returns (uint256 assets);
/// @dev Withdraws underlying tokens from a vault
function _xChainWithdrawFromVault(
InitSingleVaultData memory singleVaultData_,
address srcSender_,
uint64 srcChainId_
)
internal
virtual
returns (uint256 assets);
/// @dev withdraws vault shares from form during emergency
function _emergencyWithdraw(address receiverAddress_, uint256 amount_) internal virtual;
/// @dev forwards dust to paymaster
function _forwardDustToPaymaster(address token_) internal virtual;
/// @dev returns if a form id is paused
function _isPaused(uint256 superformId) internal view returns (bool) {
address factory = superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"));
if (!ISuperformFactory(factory).isSuperform(superformId)) {
revert Error.SUPERFORM_ID_NONEXISTENT();
}
(, uint32 formImplementationId_,) = superformId.getSuperform();
return ISuperformFactory(factory).isFormImplementationPaused(formImplementationId_);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;
/// @dev contains all the common struct and enums used for data communication between chains.
/// @dev There are two transaction types in Superform Protocol
enum TransactionType {
DEPOSIT,
WITHDRAW
}
/// @dev Message types can be INIT, RETURN (for successful Deposits) and FAIL (for failed withdraws)
enum CallbackType {
INIT,
RETURN,
FAIL
}
/// @dev Payloads are stored, updated (deposits) or processed (finalized)
enum PayloadState {
STORED,
UPDATED,
PROCESSED
}
/// @dev contains all the common struct used for interchain token transfers.
struct LiqRequest {
/// @dev generated data
bytes txData;
/// @dev input token for deposits, desired output token on target liqDstChainId for withdraws. Must be set for
/// txData to be updated on destination for withdraws
address token;
/// @dev intermediary token on destination. Relevant for xChain deposits where a destination swap is needed for
/// validation purposes
address interimToken;
/// @dev what bridge to use to move tokens
uint8 bridgeId;
/// @dev dstChainId = liqDstchainId for deposits. For withdraws it is the target chain id for where the underlying
/// is to be delivered
uint64 liqDstChainId;
/// @dev currently this amount is used as msg.value in the txData call.
uint256 nativeAmount;
}
/// @dev main struct that holds required multi vault data for an action
struct MultiVaultSFData {
// superformids must have same destination. Can have different underlyings
uint256[] superformIds;
uint256[] amounts; // on deposits, amount of token to deposit on dst, on withdrawals, superpositions to burn
uint256[] outputAmounts; // on deposits, amount of shares to receive, on withdrawals, amount of assets to receive
uint256[] maxSlippages;
LiqRequest[] liqRequests; // if length = 1; amount = sum(amounts) | else amounts must match the amounts being sent
bytes permit2data;
bool[] hasDstSwaps;
bool[] retain4626s; // if true, we don't mint SuperPositions, and send the 4626 back to the user instead
address receiverAddress;
/// this address must always be an EOA otherwise funds may be lost
address receiverAddressSP;
/// this address can be a EOA or a contract that implements onERC1155Receiver. must always be set for deposits
bytes extraFormData; // extraFormData
}
/// @dev main struct that holds required single vault data for an action
struct SingleVaultSFData {
// superformids must have same destination. Can have different underlyings
uint256 superformId;
uint256 amount;
uint256 outputAmount; // on deposits, amount of shares to receive, on withdrawals, amount of assets to receive
uint256 maxSlippage;
LiqRequest liqRequest; // if length = 1; amount = sum(amounts)| else amounts must match the amounts being sent
bytes permit2data;
bool hasDstSwap;
bool retain4626; // if true, we don't mint SuperPositions, and send the 4626 back to the user instead
address receiverAddress;
/// this address must always be an EOA otherwise funds may be lost
address receiverAddressSP;
/// this address can be a EOA or a contract that implements onERC1155Receiver. must always be set for deposits
bytes extraFormData; // extraFormData
}
/// @dev overarching struct for multiDst requests with multi vaults
struct MultiDstMultiVaultStateReq {
uint8[][] ambIds;
uint64[] dstChainIds;
MultiVaultSFData[] superformsData;
}
/// @dev overarching struct for single cross chain requests with multi vaults
struct SingleXChainMultiVaultStateReq {
uint8[] ambIds;
uint64 dstChainId;
MultiVaultSFData superformsData;
}
/// @dev overarching struct for multiDst requests with single vaults
struct MultiDstSingleVaultStateReq {
uint8[][] ambIds;
uint64[] dstChainIds;
SingleVaultSFData[] superformsData;
}
/// @dev overarching struct for single cross chain requests with single vaults
struct SingleXChainSingleVaultStateReq {
uint8[] ambIds;
uint64 dstChainId;
SingleVaultSFData superformData;
}
/// @dev overarching struct for single direct chain requests with single vaults
struct SingleDirectSingleVaultStateReq {
SingleVaultSFData superformData;
}
/// @dev overarching struct for single direct chain requests with multi vaults
struct SingleDirectMultiVaultStateReq {
MultiVaultSFData superformData;
}
/// @dev struct for SuperRouter with re-arranged data for the message (contains the payloadId)
/// @dev realize that receiverAddressSP is not passed, only needed on source chain to mint
struct InitMultiVaultData {
uint256 payloadId;
uint256[] superformIds;
uint256[] amounts;
uint256[] outputAmounts;
uint256[] maxSlippages;
LiqRequest[] liqData;
bool[] hasDstSwaps;
bool[] retain4626s;
address receiverAddress;
bytes extraFormData;
}
/// @dev struct for SuperRouter with re-arranged data for the message (contains the payloadId)
struct InitSingleVaultData {
uint256 payloadId;
uint256 superformId;
uint256 amount;
uint256 outputAmount;
uint256 maxSlippage;
LiqRequest liqData;
bool hasDstSwap;
bool retain4626;
address receiverAddress;
bytes extraFormData;
}
/// @dev struct for Emergency Queue
struct QueuedWithdrawal {
address receiverAddress;
uint256 superformId;
uint256 amount;
uint256 srcPayloadId;
bool isProcessed;
}
/// @dev all statuses of the timelock payload
enum TimelockStatus {
UNAVAILABLE,
PENDING,
PROCESSED
}
/// @dev holds information about the timelock payload
struct TimelockPayload {
uint8 isXChain;
uint64 srcChainId;
uint256 lockedTill;
InitSingleVaultData data;
TimelockStatus status;
}
/// @dev struct that contains the type of transaction, callback flags and other identification, as well as the vaults
/// data in params
struct AMBMessage {
uint256 txInfo; // tight packing of TransactionType txType, CallbackType flag if multi/single vault, registry id,
// srcSender and srcChainId
bytes params; // decoding txInfo will point to the right datatype of params. Refer PayloadHelper.sol
}
/// @dev struct that contains the information required for broadcasting changes
struct BroadcastMessage {
bytes target;
bytes32 messageType;
bytes message;
}
/// @dev struct that contains info on returned data from destination
struct ReturnMultiData {
uint256 payloadId;
uint256[] superformIds;
uint256[] amounts;
}
/// @dev struct that contains info on returned data from destination
struct ReturnSingleData {
uint256 payloadId;
uint256 superformId;
uint256 amount;
}
/// @dev struct that contains the data on the fees to pay to the AMBs
struct AMBExtraData {
uint256[] gasPerAMB;
bytes[] extraDataPerAMB;
}
/// @dev struct that contains the data on the fees to pay to the AMBs on broadcasts
struct BroadCastAMBExtraData {
uint256[] gasPerDst;
bytes[] extraDataPerDst;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;
import { Error } from "src/libraries/Error.sol";
import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol";
import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
/// @title LiquidityHandler
/// @dev Executes an action with tokens to either bridge from Chain A -> Chain B or swap on same chain
/// @dev To be inherited by contracts that move liquidity
/// @author ZeroPoint Labs
abstract contract LiquidityHandler {
using SafeERC20 for IERC20;
//////////////////////////////////////////////////////////////
// CONSTANTS //
//////////////////////////////////////////////////////////////
address constant NATIVE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
//////////////////////////////////////////////////////////////
// INTERNAL FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @dev dispatches tokens via a liquidity bridge or exchange
/// @param bridge_ Bridge address to pass tokens to
/// @param txData_ liquidity bridge data
/// @param token_ Token caller deposits into superform
/// @param amount_ Amount of tokens to deposit
/// @param nativeAmount_ msg.value or msg.value + native tokens
function _dispatchTokens(
address bridge_,
bytes memory txData_,
address token_,
uint256 amount_,
uint256 nativeAmount_
)
internal
virtual
{
if (amount_ == 0) {
revert Error.ZERO_AMOUNT();
}
if (bridge_ == address(0)) {
revert Error.ZERO_ADDRESS();
}
if (token_ != NATIVE) {
IERC20(token_).safeIncreaseAllowance(bridge_, amount_);
} else {
if (nativeAmount_ < amount_) revert Error.INSUFFICIENT_NATIVE_AMOUNT();
if (nativeAmount_ > address(this).balance) revert Error.INSUFFICIENT_BALANCE();
}
(bool success,) = payable(bridge_).call{ value: nativeAmount_ }(txData_);
if (!success) revert Error.FAILED_TO_EXECUTE_TXDATA(token_);
if (token_ != NATIVE) {
IERC20 token = IERC20(token_);
if (token.allowance(address(this), bridge_) > 0) token.forceApprove(bridge_, 0);
}
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;
/// @title Bridge Validator Interface
/// @dev Interface all Bridge Validators must follow
/// @author Zeropoint Labs
interface IBridgeValidator {
//////////////////////////////////////////////////////////////
// STRUCTS //
//////////////////////////////////////////////////////////////
struct ValidateTxDataArgs {
bytes txData;
uint64 srcChainId;
uint64 dstChainId;
uint64 liqDstChainId;
bool deposit;
address superform;
address receiverAddress;
address liqDataToken;
address liqDataInterimToken;
}
//////////////////////////////////////////////////////////////
// EXTERNAL VIEW FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @dev validates the receiver of the liquidity request
/// @param txData_ is the txData of the cross chain deposit
/// @param receiver_ is the address of the receiver to validate
/// @return valid_ if the address is valid
function validateReceiver(bytes calldata txData_, address receiver_) external view returns (bool valid_);
/// @dev validates the txData of a cross chain deposit
/// @param args_ the txData arguments to validate in txData
/// @return hasDstSwap if the txData contains a destination swap
function validateTxData(ValidateTxDataArgs calldata args_) external view returns (bool hasDstSwap);
/// @dev decodes the txData and returns the amount of input token on source
/// @param txData_ is the txData of the cross chain deposit
/// @param genericSwapDisallowed_ true if generic swaps are disallowed
/// @return amount_ the amount expected
function decodeAmountIn(
bytes calldata txData_,
bool genericSwapDisallowed_
)
external
view
returns (uint256 amount_);
/// @dev decodes neccesary information for processing swaps on the destination chain
/// @param txData_ is the txData to be decoded
/// @return token_ is the address of the token
/// @return amount_ the amount expected
function decodeDstSwap(bytes calldata txData_) external pure returns (address token_, uint256 amount_);
/// @dev decodes the final output token address (for only direct chain actions!)
/// @param txData_ is the txData to be decoded
/// @return token_ the address of the token
function decodeSwapOutputToken(bytes calldata txData_) external pure returns (address token_);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;
library Error {
//////////////////////////////////////////////////////////////
// CONFIGURATION ERRORS //
//////////////////////////////////////////////////////////////
///@notice errors thrown in protocol setup
/// @dev thrown if chain id exceeds max(uint64)
error BLOCK_CHAIN_ID_OUT_OF_BOUNDS();
/// @dev thrown if not possible to revoke a role in broadcasting
error CANNOT_REVOKE_NON_BROADCASTABLE_ROLES();
/// @dev thrown if not possible to revoke last admin
error CANNOT_REVOKE_LAST_ADMIN();
/// @dev thrown if trying to set again pseudo immutables in super registry
error DISABLED();
/// @dev thrown if rescue delay is not yet set for a chain
error DELAY_NOT_SET();
/// @dev thrown if get native token price estimate in paymentHelper is 0
error INVALID_NATIVE_TOKEN_PRICE();
/// @dev thrown if wormhole refund chain id is not set
error REFUND_CHAIN_ID_NOT_SET();
/// @dev thrown if wormhole relayer is not set
error RELAYER_NOT_SET();
/// @dev thrown if a role to be revoked is not assigned
error ROLE_NOT_ASSIGNED();
//////////////////////////////////////////////////////////////
// AUTHORIZATION ERRORS //
//////////////////////////////////////////////////////////////
///@notice errors thrown if functions cannot be called
/// COMMON AUTHORIZATION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if caller is not address(this), internal call
error INVALID_INTERNAL_CALL();
/// @dev thrown if msg.sender is not a valid amb implementation
error NOT_AMB_IMPLEMENTATION();
/// @dev thrown if msg.sender is not an allowed broadcaster
error NOT_ALLOWED_BROADCASTER();
/// @dev thrown if msg.sender is not broadcast amb implementation
error NOT_BROADCAST_AMB_IMPLEMENTATION();
/// @dev thrown if msg.sender is not broadcast state registry
error NOT_BROADCAST_REGISTRY();
/// @dev thrown if msg.sender is not core state registry
error NOT_CORE_STATE_REGISTRY();
/// @dev thrown if msg.sender is not emergency admin
error NOT_EMERGENCY_ADMIN();
/// @dev thrown if msg.sender is not emergency queue
error NOT_EMERGENCY_QUEUE();
/// @dev thrown if msg.sender is not minter
error NOT_MINTER();
/// @dev thrown if msg.sender is not minter state registry
error NOT_MINTER_STATE_REGISTRY_ROLE();
/// @dev thrown if msg.sender is not paymaster
error NOT_PAYMASTER();
/// @dev thrown if msg.sender is not payment admin
error NOT_PAYMENT_ADMIN();
/// @dev thrown if msg.sender is not protocol admin
error NOT_PROTOCOL_ADMIN();
/// @dev thrown if msg.sender is not state registry
error NOT_STATE_REGISTRY();
/// @dev thrown if msg.sender is not super registry
error NOT_SUPER_REGISTRY();
/// @dev thrown if msg.sender is not superform router
error NOT_SUPERFORM_ROUTER();
/// @dev thrown if msg.sender is not a superform
error NOT_SUPERFORM();
/// @dev thrown if msg.sender is not superform factory
error NOT_SUPERFORM_FACTORY();
/// @dev thrown if msg.sender is not timelock form
error NOT_TIMELOCK_SUPERFORM();
/// @dev thrown if msg.sender is not timelock state registry
error NOT_TIMELOCK_STATE_REGISTRY();
/// @dev thrown if msg.sender is not user or disputer
error NOT_VALID_DISPUTER();
/// @dev thrown if the msg.sender is not privileged caller
error NOT_PRIVILEGED_CALLER(bytes32 role);
/// STATE REGISTRY AUTHORIZATION ERRORS
/// ---------------------------------------------------------
/// @dev layerzero adapter specific error, thrown if caller not layerzero endpoint
error CALLER_NOT_ENDPOINT();
/// @dev hyperlane adapter specific error, thrown if caller not hyperlane mailbox
error CALLER_NOT_MAILBOX();
/// @dev wormhole relayer specific error, thrown if caller not wormhole relayer
error CALLER_NOT_RELAYER();
/// @dev thrown if src chain sender is not valid
error INVALID_SRC_SENDER();
//////////////////////////////////////////////////////////////
// INPUT VALIDATION ERRORS //
//////////////////////////////////////////////////////////////
///@notice errors thrown if input variables are not valid
/// COMMON INPUT VALIDATION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if there is an array length mismatch
error ARRAY_LENGTH_MISMATCH();
/// @dev thrown if payload id does not exist
error INVALID_PAYLOAD_ID();
/// @dev error thrown when msg value should be zero in certain payable functions
error MSG_VALUE_NOT_ZERO();
/// @dev thrown if amb ids length is 0
error ZERO_AMB_ID_LENGTH();
/// @dev thrown if address input is address 0
error ZERO_ADDRESS();
/// @dev thrown if amount input is 0
error ZERO_AMOUNT();
/// @dev thrown if final token is address 0
error ZERO_FINAL_TOKEN();
/// @dev thrown if value input is 0
error ZERO_INPUT_VALUE();
/// SUPERFORM ROUTER INPUT VALIDATION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if the vaults data is invalid
error INVALID_SUPERFORMS_DATA();
/// @dev thrown if receiver address is not set
error RECEIVER_ADDRESS_NOT_SET();
/// SUPERFORM FACTORY INPUT VALIDATION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if a form is not ERC165 compatible
error ERC165_UNSUPPORTED();
/// @dev thrown if a form is not form interface compatible
error FORM_INTERFACE_UNSUPPORTED();
/// @dev error thrown if form implementation address already exists
error FORM_IMPLEMENTATION_ALREADY_EXISTS();
/// @dev error thrown if form implementation id already exists
error FORM_IMPLEMENTATION_ID_ALREADY_EXISTS();
/// @dev thrown if a form does not exist
error FORM_DOES_NOT_EXIST();
/// @dev thrown if form id is larger than max uint16
error INVALID_FORM_ID();
/// @dev thrown if superform not on factory
error SUPERFORM_ID_NONEXISTENT();
/// @dev thrown if same vault and form implementation is used to create new superform
error VAULT_FORM_IMPLEMENTATION_COMBINATION_EXISTS();
/// FORM INPUT VALIDATION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if in case of no txData, if liqData.token != vault.asset()
/// in case of txData, if token output of swap != vault.asset()
error DIFFERENT_TOKENS();
/// @dev thrown if the amount in direct withdraw is not correct
error DIRECT_WITHDRAW_INVALID_LIQ_REQUEST();
/// @dev thrown if the amount in xchain withdraw is not correct
error XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST();
/// LIQUIDITY BRIDGE INPUT VALIDATION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if route id is blacklisted in socket
error BLACKLISTED_ROUTE_ID();
/// @dev thrown if route id is not blacklisted in socket
error NOT_BLACKLISTED_ROUTE_ID();
/// @dev error thrown when txData selector of lifi bridge is a blacklisted selector
error BLACKLISTED_SELECTOR();
/// @dev error thrown when txData selector of lifi bridge is not a blacklisted selector
error NOT_BLACKLISTED_SELECTOR();
/// @dev thrown if a certain action of the user is not allowed given the txData provided
error INVALID_ACTION();
/// @dev thrown if in deposits, the liqDstChainId doesn't match the stateReq dstChainId
error INVALID_DEPOSIT_LIQ_DST_CHAIN_ID();
/// @dev thrown if index is invalid
error INVALID_INDEX();
/// @dev thrown if the chain id in the txdata is invalid
error INVALID_TXDATA_CHAIN_ID();
/// @dev thrown if the validation of bridge txData fails due to a destination call present
error INVALID_TXDATA_NO_DESTINATIONCALL_ALLOWED();
/// @dev thrown if the validation of bridge txData fails due to wrong receiver
error INVALID_TXDATA_RECEIVER();
/// @dev thrown if the validation of bridge txData fails due to wrong token
error INVALID_TXDATA_TOKEN();
/// @dev thrown if txData is not present (in case of xChain actions)
error NO_TXDATA_PRESENT();
/// STATE REGISTRY INPUT VALIDATION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if payload is being updated with final amounts length different than amounts length
error DIFFERENT_PAYLOAD_UPDATE_AMOUNTS_LENGTH();
/// @dev thrown if payload is being updated with tx data length different than liq data length
error DIFFERENT_PAYLOAD_UPDATE_TX_DATA_LENGTH();
/// @dev thrown if keeper update final token is different than the vault underlying
error INVALID_UPDATE_FINAL_TOKEN();
/// @dev thrown if broadcast finality for wormhole is invalid
error INVALID_BROADCAST_FINALITY();
/// @dev thrown if amb id is not valid leading to an address 0 of the implementation
error INVALID_BRIDGE_ID();
/// @dev thrown if chain id involved in xchain message is invalid
error INVALID_CHAIN_ID();
/// @dev thrown if payload update amount isn't equal to dst swapper amount
error INVALID_DST_SWAP_AMOUNT();
/// @dev thrown if message amb and proof amb are the same
error INVALID_PROOF_BRIDGE_ID();
/// @dev thrown if order of proof AMBs is incorrect, either duplicated or not incrementing
error INVALID_PROOF_BRIDGE_IDS();
/// @dev thrown if rescue data lengths are invalid
error INVALID_RESCUE_DATA();
/// @dev thrown if delay is invalid
error INVALID_TIMELOCK_DELAY();
/// @dev thrown if amounts being sent in update payload mean a negative slippage
error NEGATIVE_SLIPPAGE();
/// @dev thrown if slippage is outside of bounds
error SLIPPAGE_OUT_OF_BOUNDS();
/// SUPERPOSITION INPUT VALIDATION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if src senders mismatch in state sync
error SRC_SENDER_MISMATCH();
/// @dev thrown if src tx types mismatch in state sync
error SRC_TX_TYPE_MISMATCH();
//////////////////////////////////////////////////////////////
// EXECUTION ERRORS //
//////////////////////////////////////////////////////////////
///@notice errors thrown due to function execution logic
/// COMMON EXECUTION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if the swap in a direct deposit resulted in insufficient tokens
error DIRECT_DEPOSIT_SWAP_FAILED();
/// @dev thrown if payload is not unique
error DUPLICATE_PAYLOAD();
/// @dev thrown if native tokens fail to be sent to superform contracts
error FAILED_TO_SEND_NATIVE();
/// @dev thrown if allowance is not correct to deposit
error INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT();
/// @dev thrown if contract has insufficient balance for operations
error INSUFFICIENT_BALANCE();
/// @dev thrown if native amount is not at least equal to the amount in the request
error INSUFFICIENT_NATIVE_AMOUNT();
/// @dev thrown if payload cannot be decoded
error INVALID_PAYLOAD();
/// @dev thrown if payload status is invalid
error INVALID_PAYLOAD_STATUS();
/// @dev thrown if payload type is invalid
error INVALID_PAYLOAD_TYPE();
/// LIQUIDITY BRIDGE EXECUTION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if we try to decode the final swap output token in a xChain liquidity bridging action
error CANNOT_DECODE_FINAL_SWAP_OUTPUT_TOKEN();
/// @dev thrown if liquidity bridge fails for erc20 or native tokens
error FAILED_TO_EXECUTE_TXDATA(address token);
/// @dev thrown if asset being used for deposit mismatches in multivault deposits
error INVALID_DEPOSIT_TOKEN();
/// STATE REGISTRY EXECUTION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if bridge tokens haven't arrived to destination
error BRIDGE_TOKENS_PENDING();
/// @dev thrown if withdrawal tx data cannot be updated
error CANNOT_UPDATE_WITHDRAW_TX_DATA();
/// @dev thrown if rescue passed dispute deadline
error DISPUTE_TIME_ELAPSED();
/// @dev thrown if message failed to reach the specified level of quorum needed
error INSUFFICIENT_QUORUM();
/// @dev thrown if broadcast payload is invalid
error INVALID_BROADCAST_PAYLOAD();
/// @dev thrown if broadcast fee is invalid
error INVALID_BROADCAST_FEE();
/// @dev thrown if retry fees is less than required
error INVALID_RETRY_FEE();
/// @dev thrown if broadcast message type is wrong
error INVALID_MESSAGE_TYPE();
/// @dev thrown if payload hash is invalid during `retryMessage` on Layezero implementation
error INVALID_PAYLOAD_HASH();
/// @dev thrown if update payload function was called on a wrong payload
error INVALID_PAYLOAD_UPDATE_REQUEST();
/// @dev thrown if a state registry id is 0
error INVALID_REGISTRY_ID();
/// @dev thrown if a form state registry id is 0
error INVALID_FORM_REGISTRY_ID();
/// @dev thrown if trying to finalize the payload but the withdraw is still locked
error LOCKED();
/// @dev thrown if payload is already updated (during xChain deposits)
error PAYLOAD_ALREADY_UPDATED();
/// @dev thrown if payload is already processed
error PAYLOAD_ALREADY_PROCESSED();
/// @dev thrown if payload is not in UPDATED state
error PAYLOAD_NOT_UPDATED();
/// @dev thrown if rescue is still in timelocked state
error RESCUE_LOCKED();
/// @dev thrown if rescue is already proposed
error RESCUE_ALREADY_PROPOSED();
/// @dev thrown if payload hash is zero during `retryMessage` on Layezero implementation
error ZERO_PAYLOAD_HASH();
/// DST SWAPPER EXECUTION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if process dst swap is tried for processed payload id
error DST_SWAP_ALREADY_PROCESSED();
/// @dev thrown if indices have duplicates
error DUPLICATE_INDEX();
/// @dev thrown if failed dst swap is already updated
error FAILED_DST_SWAP_ALREADY_UPDATED();
/// @dev thrown if indices are out of bounds
error INDEX_OUT_OF_BOUNDS();
/// @dev thrown if failed swap token amount is 0
error INVALID_DST_SWAPPER_FAILED_SWAP();
/// @dev thrown if failed swap token amount is not 0 and if token balance is less than amount (non zero)
error INVALID_DST_SWAPPER_FAILED_SWAP_NO_TOKEN_BALANCE();
/// @dev thrown if failed swap token amount is not 0 and if native amount is less than amount (non zero)
error INVALID_DST_SWAPPER_FAILED_SWAP_NO_NATIVE_BALANCE();
/// @dev forbid xChain deposits with destination swaps without interim token set (for user protection)
error INVALID_INTERIM_TOKEN();
/// @dev thrown if dst swap output is less than minimum expected
error INVALID_SWAP_OUTPUT();
/// FORM EXECUTION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if try to forward 4626 share from the superform
error CANNOT_FORWARD_4646_TOKEN();
/// @dev thrown in KYCDAO form if no KYC token is present
error NO_VALID_KYC_TOKEN();
/// @dev thrown in forms where a certain functionality is not allowed or implemented
error NOT_IMPLEMENTED();
/// @dev thrown if form implementation is PAUSED, users cannot perform any action
error PAUSED();
/// @dev thrown if shares != deposit output or assets != redeem output when minting SuperPositions
error VAULT_IMPLEMENTATION_FAILED();
/// @dev thrown if withdrawal tx data is not updated
error WITHDRAW_TOKEN_NOT_UPDATED();
/// @dev thrown if withdrawal tx data is not updated
error WITHDRAW_TX_DATA_NOT_UPDATED();
/// @dev thrown when redeeming from vault yields zero collateral
error WITHDRAW_ZERO_COLLATERAL();
/// PAYMENT HELPER EXECUTION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if chainlink is reporting an improper price
error CHAINLINK_MALFUNCTION();
/// @dev thrown if chainlink is reporting an incomplete round
error CHAINLINK_INCOMPLETE_ROUND();
/// @dev thrown if feed decimals is not 8
error CHAINLINK_UNSUPPORTED_DECIMAL();
/// EMERGENCY QUEUE EXECUTION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if emergency withdraw is not queued
error EMERGENCY_WITHDRAW_NOT_QUEUED();
/// @dev thrown if emergency withdraw is already processed
error EMERGENCY_WITHDRAW_PROCESSED_ALREADY();
/// SUPERPOSITION EXECUTION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if uri cannot be updated
error DYNAMIC_URI_FROZEN();
/// @dev thrown if tx history is not found while state sync
error TX_HISTORY_NOT_FOUND();
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;
import { Error } from "src/libraries/Error.sol";
library DataLib {
function packTxInfo(
uint8 txType_,
uint8 callbackType_,
uint8 multi_,
uint8 registryId_,
address srcSender_,
uint64 srcChainId_
)
internal
pure
returns (uint256 txInfo)
{
txInfo = uint256(txType_);
txInfo |= uint256(callbackType_) << 8;
txInfo |= uint256(multi_) << 16;
txInfo |= uint256(registryId_) << 24;
txInfo |= uint256(uint160(srcSender_)) << 32;
txInfo |= uint256(srcChainId_) << 192;
}
function decodeTxInfo(uint256 txInfo_)
internal
pure
returns (uint8 txType, uint8 callbackType, uint8 multi, uint8 registryId, address srcSender, uint64 srcChainId)
{
txType = uint8(txInfo_);
callbackType = uint8(txInfo_ >> 8);
multi = uint8(txInfo_ >> 16);
registryId = uint8(txInfo_ >> 24);
srcSender = address(uint160(txInfo_ >> 32));
srcChainId = uint64(txInfo_ >> 192);
}
/// @dev returns the vault-form-chain pair of a superform
/// @param superformId_ is the id of the superform
/// @return superform_ is the address of the superform
/// @return formImplementationId_ is the form id
/// @return chainId_ is the chain id
function getSuperform(uint256 superformId_)
internal
pure
returns (address superform_, uint32 formImplementationId_, uint64 chainId_)
{
superform_ = address(uint160(superformId_));
formImplementationId_ = uint32(superformId_ >> 160);
chainId_ = uint64(superformId_ >> 192);
if (chainId_ == 0) {
revert Error.INVALID_CHAIN_ID();
}
}
/// @dev returns the vault-form-chain pair of an array of superforms
/// @param superformIds_ array of superforms
/// @return superforms_ are the address of the vaults
function getSuperforms(uint256[] memory superformIds_) internal pure returns (address[] memory superforms_) {
uint256 len = superformIds_.length;
superforms_ = new address[](len);
for (uint256 i; i < len; ++i) {
(superforms_[i],,) = getSuperform(superformIds_[i]);
}
}
/// @dev returns the destination chain of a given superform
/// @param superformId_ is the id of the superform
/// @return chainId_ is the chain id
function getDestinationChain(uint256 superformId_) internal pure returns (uint64 chainId_) {
chainId_ = uint64(superformId_ >> 192);
if (chainId_ == 0) {
revert Error.INVALID_CHAIN_ID();
}
}
/// @dev generates the superformId
/// @param superform_ is the address of the superform
/// @param formImplementationId_ is the type of the form
/// @param chainId_ is the chain id on which the superform is deployed
function packSuperform(
address superform_,
uint32 formImplementationId_,
uint64 chainId_
)
internal
pure
returns (uint256 superformId_)
{
superformId_ = uint256(uint160(superform_));
superformId_ |= uint256(formImplementationId_) << 160;
superformId_ |= uint256(chainId_) << 192;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC-20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev An operation with an ERC-20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC4626.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";
import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol";
/**
* @dev Interface of the ERC-4626 "Tokenized Vault Standard", as defined in
* https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].
*/
interface IERC4626 is IERC20, IERC20Metadata {
event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed sender,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
/**
* @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
*
* - MUST be an ERC-20 token contract.
* - MUST NOT revert.
*/
function asset() external view returns (address assetTokenAddress);
/**
* @dev Returns the total amount of the underlying asset that is “managed” by Vault.
*
* - SHOULD include any compounding that occurs from yield.
* - MUST be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT revert.
*/
function totalAssets() external view returns (uint256 totalManagedAssets);
/**
* @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToShares(uint256 assets) external view returns (uint256 shares);
/**
* @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToAssets(uint256 shares) external view returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
* through a deposit call.
*
* - MUST return a limited value if receiver is subject to some deposit limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
* - MUST NOT revert.
*/
function maxDeposit(address receiver) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
* call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
* in the same transaction.
* - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
* deposit would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewDeposit(uint256 assets) external view returns (uint256 shares);
/**
* @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* deposit execution, and are accounted for during deposit.
* - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
* - MUST return a limited value if receiver is subject to some mint limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
* - MUST NOT revert.
*/
function maxMint(address receiver) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
* in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
* same transaction.
* - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
* would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by minting.
*/
function previewMint(uint256 shares) external view returns (uint256 assets);
/**
* @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
* execution, and are accounted for during mint.
* - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function mint(uint256 shares, address receiver) external returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
* Vault, through a withdraw call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxWithdraw(address owner) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
* call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
* called
* in the same transaction.
* - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
* the withdrawal would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewWithdraw(uint256 assets) external view returns (uint256 shares);
/**
* @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* withdraw execution, and are accounted for during withdraw.
* - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
* through a redeem call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxRedeem(address owner) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
* in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
* same transaction.
* - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
* redemption would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by redeeming.
*/
function previewRedeem(uint256 shares) external view returns (uint256 assets);
/**
* @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* redeem execution, and are accounted for during redeem.
* - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;
import { InitSingleVaultData } from "src/types/DataTypes.sol";
import { IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol";
import { IERC4626 } from "openzeppelin-contracts/contracts/interfaces/IERC4626.sol";
/// @title IBaseForm
/// @dev Interface for BaseForm
/// @author ZeroPoint Labs
interface IBaseForm is IERC165 {
//////////////////////////////////////////////////////////////
// EVENTS //
//////////////////////////////////////////////////////////////
/// @dev is emitted when a new vault is added by the admin.
event VaultAdded(uint256 indexed id, IERC4626 indexed vault);
/// @dev is emitted when a payload is processed by the destination contract.
event Processed(
uint64 indexed srcChainID,
uint64 indexed dstChainId,
uint256 indexed srcPayloadId,
uint256 amount,
address vault
);
/// @dev is emitted when an emergency withdrawal is processed
event EmergencyWithdrawalProcessed(address indexed refundAddress, uint256 indexed amount);
/// @dev is emitted when dust is forwarded to the paymaster
event FormDustForwardedToPaymaster(address indexed token, uint256 indexed amount);
//////////////////////////////////////////////////////////////
// EXTERNAL VIEW FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @notice get Superform name of the ERC20 vault representation
/// @return The ERC20 name
function superformYieldTokenName() external view returns (string memory);
/// @notice get Superform symbol of the ERC20 vault representation
/// @return The ERC20 symbol
function superformYieldTokenSymbol() external view returns (string memory);
/// @notice get the state registry id associated with the vault
function getStateRegistryId() external view returns (uint8);
/// @notice Returns the vault address
/// @return The address of the vault
function getVaultAddress() external view returns (address);
/// @notice Returns the vault address
/// @return The address of the vault asset
function getVaultAsset() external view returns (address);
/// @notice Returns the name of the vault.
/// @return The name of the vault
function getVaultName() external view returns (string memory);
/// @notice Returns the symbol of a vault.
/// @return The symbol associated with a vault
function getVaultSymbol() external view returns (string memory);
/// @notice Returns the number of decimals in a vault for accounting purposes
/// @return The number of decimals in the vault balance
function getVaultDecimals() external view returns (uint256);
/// @notice Returns the amount of underlying tokens each share of a vault is worth.
/// @return The pricePerVaultShare value
function getPricePerVaultShare() external view returns (uint256);
/// @notice Returns the amount of vault shares owned by the form.
/// @return The form's vault share balance
function getVaultShareBalance() external view returns (uint256);
/// @notice get the total amount of underlying managed in the ERC4626 vault
function getTotalAssets() external view returns (uint256);
/// @notice get the total amount of unredeemed vault shares in circulation
function getTotalSupply() external view returns (uint256);
/// @notice get the total amount of assets received if shares are actually redeemed
/// @notice https://eips.ethereum.org/EIPS/eip-4626
function getPreviewPricePerVaultShare() external view returns (uint256);
/// @dev API may need to know state of funds deployed
function previewDepositTo(uint256 assets_) external view returns (uint256);
/// @notice positionBalance() -> .vaultIds&destAmounts
/// @return how much of an asset + interest (accrued) is to withdraw from the Vault
function previewWithdrawFrom(uint256 assets_) external view returns (uint256);
/// @dev API may need to know state of funds deployed
function previewRedeemFrom(uint256 shares_) external view returns (uint256);
//////////////////////////////////////////////////////////////
// EXTERNAL WRITE FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @dev process same chain id deposits
/// @param singleVaultData_ A bytes representation containing all the data required to make a form action
/// @param srcSender_ The address of the sender of the transaction
/// @return shares The amount of vault shares received
function directDepositIntoVault(
InitSingleVaultData memory singleVaultData_,
address srcSender_
)
external
payable
returns (uint256 shares);
/// @dev process same chain id deposits
/// @param singleVaultData_ A bytes representation containing all the data required to make a form action
/// @param srcSender_ The address of the sender of the transaction
/// @param srcChainId_ The chain id of the source chain
/// @return shares The amount of vault shares received
/// @dev is shares is `0` then no further action/acknowledgement needs to be sent
function xChainDepositIntoVault(
InitSingleVaultData memory singleVaultData_,
address srcSender_,
uint64 srcChainId_
)
external
returns (uint256 shares);
/// @dev process withdrawal of asset from a vault
/// @param singleVaultData_ A bytes representation containing all the data required to make a form action
/// @param srcSender_ The address of the sender of the transaction
/// @return assets The amount of assets received
function directWithdrawFromVault(
InitSingleVaultData memory singleVaultData_,
address srcSender_
)
external
returns (uint256 assets);
/// @dev process withdrawal of asset from a vault
/// @param singleVaultData_ A bytes representation containing all the data required to make a form action
/// @param srcSender_ The address of the sender of the transaction
/// @param srcChainId_ The chain id of the source chain
/// @return assets The amount of assets received
function xChainWithdrawFromVault(
InitSingleVaultData memory singleVaultData_,
address srcSender_,
uint64 srcChainId_
)
external
returns (uint256 assets);
/// @dev process withdrawal of shares if form is paused
/// @param receiverAddress_ The address to refund the shares to
/// @param amount_ The amount of vault shares to refund
function emergencyWithdraw(address receiverAddress_, uint256 amount_) external;
/// @dev moves all dust in the contract to Paymaster contract
/// @param token_ The address of the token to forward
function forwardDustToPaymaster(address token_) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;
/// @title ISuperRegistry
/// @dev Interface for SuperRegistry
/// @author Zeropoint Labs
interface ISuperRegistry {
//////////////////////////////////////////////////////////////
// EVENTS //
//////////////////////////////////////////////////////////////
/// @dev emitted when permit2 is set.
event SetPermit2(address indexed permit2);
/// @dev is emitted when an address is set.
event AddressUpdated(
bytes32 indexed protocolAddressId, uint64 indexed chainId, address indexed oldAddress, address newAddress
);
/// @dev is emitted when a new token bridge is configured.
event SetBridgeAddress(uint256 indexed bridgeId, address indexed bridgeAddress);
/// @dev is emitted when a new bridge validator is configured.
event SetBridgeValidator(uint256 indexed bridgeId, address indexed bridgeValidator);
/// @dev is emitted when a new amb is configured.
event SetAmbAddress(uint8 indexed ambId_, address indexed ambAddress_, bool indexed isBroadcastAMB_);
/// @dev is emitted when a new state registry is configured.
event SetStateRegistryAddress(uint8 indexed registryId_, address indexed registryAddress_);
/// @dev is emitted when a new delay is configured.
event SetDelay(uint256 indexed oldDelay_, uint256 indexed newDelay_);
/// @dev is emitted when a new vault limit is configured
event SetVaultLimitPerDestination(uint64 indexed chainId_, uint256 indexed vaultLimit_);
//////////////////////////////////////////////////////////////
// EXTERNAL VIEW FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @dev gets the deposit rescue delay
function delay() external view returns (uint256);
/// @dev returns the permit2 address
function PERMIT2() external view returns (address);
/// @dev returns the id of the superform router module
function SUPERFORM_ROUTER() external view returns (bytes32);
/// @dev returns the id of the superform factory module
function SUPERFORM_FACTORY() external view returns (bytes32);
/// @dev returns the id of the superform paymaster contract
function PAYMASTER() external view returns (bytes32);
/// @dev returns the id of the superform payload helper contract
function PAYMENT_HELPER() external view returns (bytes32);
/// @dev returns the id of the core state registry module
function CORE_STATE_REGISTRY() external view returns (bytes32);
/// @dev returns the id of the timelock form state registry module
function TIMELOCK_STATE_REGISTRY() external view returns (bytes32);
/// @dev returns the id of the broadcast state registry module
function BROADCAST_REGISTRY() external view returns (bytes32);
/// @dev returns the id of the super positions module
function SUPER_POSITIONS() external view returns (bytes32);
/// @dev returns the id of the super rbac module
function SUPER_RBAC() external view returns (bytes32);
/// @dev returns the id of the payload helper module
function PAYLOAD_HELPER() external view returns (bytes32);
/// @dev returns the id of the dst swapper keeper
function DST_SWAPPER() external view returns (bytes32);
/// @dev returns the id of the emergency queue
function EMERGENCY_QUEUE() external view returns (bytes32);
/// @dev returns the id of the superform receiver
function SUPERFORM_RECEIVER() external view returns (bytes32);
/// @dev returns the id of the payment admin keeper
function PAYMENT_ADMIN() external view returns (bytes32);
/// @dev returns the id of the core state registry processor keeper
function CORE_REGISTRY_PROCESSOR() external view returns (bytes32);
/// @dev returns the id of the broadcast registry processor keeper
function BROADCAST_REGISTRY_PROCESSOR() external view returns (bytes32);
/// @dev returns the id of the timelock form state registry processor keeper
function TIMELOCK_REGISTRY_PROCESSOR() external view returns (bytes32);
/// @dev returns the id of the core state registry updater keeper
function CORE_REGISTRY_UPDATER() external view returns (bytes32);
/// @dev returns the id of the core state registry updater keeper
function CORE_REGISTRY_RESCUER() external view returns (bytes32);
/// @dev returns the id of the core state registry updater keeper
function CORE_REGISTRY_DISPUTER() external view returns (bytes32);
/// @dev returns the id of the core state registry updater keeper
function DST_SWAPPER_PROCESSOR() external view returns (bytes32);
/// @dev gets the address of a contract on current chain
/// @param id_ is the id of the contract
function getAddress(bytes32 id_) external view returns (address);
/// @dev gets the address of a contract on a target chain
/// @param id_ is the id of the contract
/// @param chainId_ is the chain id of that chain
function getAddressByChainId(bytes32 id_, uint64 chainId_) external view returns (address);
/// @dev gets the address of a bridge
/// @param bridgeId_ is the id of a bridge
/// @return bridgeAddress_ is the address of the form
function getBridgeAddress(uint8 bridgeId_) external view returns (address bridgeAddress_);
/// @dev gets the address of a bridge validator
/// @param bridgeId_ is the id of a bridge
/// @return bridgeValidator_ is the address of the form
function getBridgeValidator(uint8 bridgeId_) external view returns (address bridgeValidator_);
/// @dev gets the address of a amb
/// @param ambId_ is the id of a bridge
/// @return ambAddress_ is the address of the form
function getAmbAddress(uint8 ambId_) external view returns (address ambAddress_);
/// @dev gets the id of the amb
/// @param ambAddress_ is the address of an amb
/// @return ambId_ is the identifier of an amb
function getAmbId(address ambAddress_) external view returns (uint8 ambId_);
/// @dev gets the address of the registry
/// @param registryId_ is the id of the state registry
/// @return registryAddress_ is the address of the state registry
function getStateRegistry(uint8 registryId_) external view returns (address registryAddress_);
/// @dev gets the id of the registry
/// @notice reverts if the id is not found
/// @param registryAddress_ is the address of the state registry
/// @return registryId_ is the id of the state registry
function getStateRegistryId(address registryAddress_) external view returns (uint8 registryId_);
/// @dev gets the safe vault limit
/// @param chainId_ is the id of the remote chain
/// @return vaultLimitPerDestination_ is the safe number of vaults to deposit
/// without hitting out of gas error
function getVaultLimitPerDestination(uint64 chainId_) external view returns (uint256 vaultLimitPerDestination_);
/// @dev helps validate if an address is a valid state registry
/// @param registryAddress_ is the address of the state registry
/// @return valid_ a flag indicating if its valid.
function isValidStateRegistry(address registryAddress_) external view returns (bool valid_);
/// @dev helps validate if an address is a valid amb implementation
/// @param ambAddress_ is the address of the amb implementation
/// @return valid_ a flag indicating if its valid.
function isValidAmbImpl(address ambAddress_) external view returns (bool valid_);
/// @dev helps validate if an address is a valid broadcast amb implementation
/// @param ambAddress_ is the address of the broadcast amb implementation
/// @return valid_ a flag indicating if its valid.
function isValidBroadcastAmbImpl(address ambAddress_) external view returns (bool valid_);
//////////////////////////////////////////////////////////////
// EXTERNAL WRITE FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @dev sets the deposit rescue delay
/// @param delay_ the delay in seconds before the deposit rescue can be finalized
function setDelay(uint256 delay_) external;
/// @dev sets the permit2 address
/// @param permit2_ the address of the permit2 contract
function setPermit2(address permit2_) external;
/// @dev sets the safe vault limit
/// @param chainId_ is the remote chain identifier
/// @param vaultLimit_ is the max limit of vaults per transaction
function setVaultLimitPerDestination(uint64 chainId_, uint256 vaultLimit_) external;
/// @dev sets new addresses on specific chains.
/// @param ids_ are the identifiers of the address on that chain
/// @param newAddresses_ are the new addresses on that chain
/// @param chainIds_ are the chain ids of that chain
function batchSetAddress(
bytes32[] calldata ids_,
address[] calldata newAddresses_,
uint64[] calldata chainIds_
)
external;
/// @dev sets a new address on a specific chain.
/// @param id_ the identifier of the address on that chain
/// @param newAddress_ the new address on that chain
/// @param chainId_ the chain id of that chain
function setAddress(bytes32 id_, address newAddress_, uint64 chainId_) external;
/// @dev allows admin to set the bridge address for an bridge id.
/// @notice this function operates in an APPEND-ONLY fashion.
/// @param bridgeId_ represents the bridge unique identifier.
/// @param bridgeAddress_ represents the bridge address.
/// @param bridgeValidator_ represents the bridge validator address.
function setBridgeAddresses(
uint8[] memory bridgeId_,
address[] memory bridgeAddress_,
address[] memory bridgeValidator_
)
external;
/// @dev allows admin to set the amb address for an amb id.
/// @notice this function operates in an APPEND-ONLY fashion.
/// @param ambId_ represents the bridge unique identifier.
/// @param ambAddress_ represents the bridge address.
/// @param isBroadcastAMB_ represents whether the amb implementation supports broadcasting
function setAmbAddress(
uint8[] memory ambId_,
address[] memory ambAddress_,
bool[] memory isBroadcastAMB_
)
external;
/// @dev allows admin to set the state registry address for an state registry id.
/// @notice this function operates in an APPEND-ONLY fashion.
/// @param registryId_ represents the state registry's unique identifier.
/// @param registryAddress_ represents the state registry's address.
function setStateRegistryAddress(uint8[] memory registryId_, address[] memory registryAddress_) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;
/// @title ISuperformFactory
/// @dev Interface for SuperformFactory
/// @author ZeroPoint Labs
interface ISuperformFactory {
//////////////////////////////////////////////////////////////
// CONSTANTS //
//////////////////////////////////////////////////////////////
enum PauseStatus {
NON_PAUSED,
PAUSED
}
//////////////////////////////////////////////////////////////
// EVENTS //
//////////////////////////////////////////////////////////////
/// @dev emitted when a new formImplementation is entered into the factory
/// @param formImplementation is the address of the new form implementation
/// @param formImplementationId is the id of the formImplementation
/// @param formStateRegistryId is any additional state registry id of the formImplementation
event FormImplementationAdded(
address indexed formImplementation, uint256 indexed formImplementationId, uint8 indexed formStateRegistryId
);
/// @dev emitted when a new Superform is created
/// @param formImplementationId is the id of the form implementation
/// @param vault is the address of the vault
/// @param superformId is the id of the superform
/// @param superform is the address of the superform
event SuperformCreated(
uint256 indexed formImplementationId, address indexed vault, uint256 indexed superformId, address superform
);
/// @dev emitted when a new SuperRegistry is set
/// @param superRegistry is the address of the super registry
event SuperRegistrySet(address indexed superRegistry);
/// @dev emitted when a form implementation is paused
/// @param formImplementationId is the id of the form implementation
/// @param paused is the new paused status
event FormImplementationPaused(uint256 indexed formImplementationId, PauseStatus indexed paused);
//////////////////////////////////////////////////////////////
// EXTERNAL VIEW FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @dev returns the number of forms
/// @return forms_ is the number of forms
function getFormCount() external view returns (uint256 forms_);
/// @dev returns the number of superforms
/// @return superforms_ is the number of superforms
function getSuperformCount() external view returns (uint256 superforms_);
/// @dev returns the address of a form implementation
/// @param formImplementationId_ is the id of the form implementation
/// @return formImplementation_ is the address of the form implementation
function getFormImplementation(uint32 formImplementationId_) external view returns (address formImplementation_);
/// @dev returns the form state registry id of a form implementation
/// @param formImplementationId_ is the id of the form implementation
/// @return stateRegistryId_ is the additional state registry id of the form
function getFormStateRegistryId(uint32 formImplementationId_) external view returns (uint8 stateRegistryId_);
/// @dev returns the paused status of form implementation
/// @param formImplementationId_ is the id of the form implementation
/// @return paused_ is the current paused status of the form formImplementationId_
function isFormImplementationPaused(uint32 formImplementationId_) external view returns (bool paused_);
/// @dev returns the address of a superform
/// @param superformId_ is the id of the superform
/// @return superform_ is the address of the superform
/// @return formImplementationId_ is the id of the form implementation
/// @return chainId_ is the chain id
function getSuperform(uint256 superformId_)
external
pure
returns (address superform_, uint32 formImplementationId_, uint64 chainId_);
/// @dev returns if an address has been added to a Form
/// @param superformId_ is the id of the superform
/// @return isSuperform_ bool if it exists
function isSuperform(uint256 superformId_) external view returns (bool isSuperform_);
/// @dev Reverse query of getSuperform, returns all superforms for a given vault
/// @param vault_ is the address of a vault
/// @return superformIds_ is the id of the superform
/// @return superforms_ is the address of the superform
function getAllSuperformsFromVault(address vault_)
external
view
returns (uint256[] memory superformIds_, address[] memory superforms_);
//////////////////////////////////////////////////////////////
// EXTERNAL WRITE FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @dev allows an admin to add a Form implementation to the factory
/// @param formImplementation_ is the address of a form implementation
/// @param formImplementationId_ is the id of the form implementation (generated off-chain and equal in all chains)
/// @param formStateRegistryId_ is the id of any additional state registry for that form
/// @dev formStateRegistryId_ 1 is default for all form implementations, pass in formStateRegistryId_ only if an
/// additional state registry is required
function addFormImplementation(
address formImplementation_,
uint32 formImplementationId_,
uint8 formStateRegistryId_
)
external;
/// @dev To add new vaults to Form implementations, fusing them together into Superforms
/// @param formImplementationId_ is the form implementation we want to attach the vault to
/// @param vault_ is the address of the vault
/// @return superformId_ is the id of the created superform
/// @return superform_ is the address of the created superform
function createSuperform(
uint32 formImplementationId_,
address vault_
)
external
returns (uint256 superformId_, address superform_);
/// @dev to synchronize superforms added to different chains using broadcast registry
/// @param data_ is the cross-chain superform id
function stateSyncBroadcast(bytes memory data_) external payable;
/// @dev allows an admin to change the status of a form
/// @param formImplementationId_ is the id of the form implementation
/// @param status_ is the new status
/// @param extraData_ is optional & passed when broadcasting of status is needed
function changeFormImplementationPauseStatus(
uint32 formImplementationId_,
PauseStatus status_,
bytes memory extraData_
)
external
payable;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;
import { InitSingleVaultData } from "src/types/DataTypes.sol";
/// @title IEmergencyQueue
/// @dev Interface for EmergencyQueue
/// @author ZeroPoint Labs
interface IEmergencyQueue {
//////////////////////////////////////////////////////////////
// EVENTS //
//////////////////////////////////////////////////////////////
event WithdrawalQueued(
address indexed receiverAddress,
uint256 indexed id,
uint256 indexed superformId,
uint256 amount,
uint256 srcPayloadId
);
event WithdrawalProcessed(
address indexed refundAddress, uint256 indexed id, uint256 indexed superformId, uint256 amount
);
//////////////////////////////////////////////////////////////
// EXTERNAL VIEW FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @dev returns the execution status of an id in the emergency queue
/// @param id is the identifier of the queued action
/// @return boolean representing the execution status
function queuedWithdrawalStatus(uint256 id) external view returns (bool);
//////////////////////////////////////////////////////////////
// EXTERNAL WRITE FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @dev called by paused forms to queue up withdrawals for exit
/// @param data_ is the single vault data passed by the user
function queueWithdrawal(InitSingleVaultData memory data_) external;
/// @dev called by emergency admin to processed queued withdrawal
/// @param id_ is the identifier of the queued action
function executeQueuedWithdrawal(uint256 id_) external;
/// @dev called by emergency admin to batch process queued withdrawals
/// @param ids_ is the array of identifiers of the queued actions
function batchExecuteQueuedWithdrawal(uint256[] memory ids_) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.20;
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Storage of the initializable contract.
*
* It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
* when using with upgradeable contracts.
*
* @custom:storage-location erc7201:openzeppelin.storage.Initializable
*/
struct InitializableStorage {
/**
* @dev Indicates that the contract has been initialized.
*/
uint64 _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool _initializing;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;
/**
* @dev The contract is already initialized.
*/
error InvalidInitialization();
/**
* @dev The contract is not initializing.
*/
error NotInitializing();
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint64 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
* number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
* production.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
// Cache values to avoid duplicated sloads
bool isTopLevelCall = !$._initializing;
uint64 initialized = $._initialized;
// Allowed calls:
// - initialSetup: the contract is not in the initializing state and no previous version was
// initialized
// - construction: the contract is initialized at version 1 (no reininitialization) and the
// current contract is just being deployed
bool initialSetup = initialized == 0 && isTopLevelCall;
bool construction = initialized == 1 && address(this).code.length == 0;
if (!initialSetup && !construction) {
revert InvalidInitialization();
}
$._initialized = 1;
if (isTopLevelCall) {
$._initializing = true;
}
_;
if (isTopLevelCall) {
$._initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint64 version) {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing || $._initialized >= version) {
revert InvalidInitialization();
}
$._initialized = version;
$._initializing = true;
_;
$._initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
_checkInitializing();
_;
}
/**
* @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
*/
function _checkInitializing() internal view virtual {
if (!_isInitializing()) {
revert NotInitializing();
}
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing) {
revert InvalidInitialization();
}
if ($._initialized != type(uint64).max) {
$._initialized = type(uint64).max;
emit Initialized(type(uint64).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint64) {
return _getInitializableStorage()._initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _getInitializableStorage()._initializing;
}
/**
* @dev Returns a pointer to the storage namespace.
*/
// solhint-disable-next-line var-name-mixedcase
function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
assembly {
$.slot := INITIALIZABLE_STORAGE
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` 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 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error AddressInsufficientBalance(address account);
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedInnerCall();
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
/**
* @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 or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {FailedInnerCall} error.
*
* 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.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @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`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
* unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {FailedInnerCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
*/
function _revert(bytes memory returndata) 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 FailedInnerCall();
}
}
}{
"remappings": [
"solmate/=lib/ERC1155A/lib/solmate/src/",
"ERC1155A/=lib/ERC1155A/src/",
"@openzeppelin/contracts/=lib/ERC1155A/lib/openzeppelin-contracts/contracts/",
"ds-test/=lib/ds-test/src/",
"erc4626-tests/=lib/ERC1155A/lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts/=lib/ERC1155A/lib/openzeppelin-contracts/",
"pigeon/=lib/pigeon/src/",
"solady/=lib/pigeon/lib/solady/",
"super-vaults/=lib/super-vaults/src/",
"v2-core/=lib/super-vaults/lib/v2-core/contracts/",
"v2-periphery/=lib/super-vaults/lib/v2-periphery/contracts/",
"v3-core/=lib/super-vaults/lib/v3-core/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"superRegistry_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"BLOCK_CHAIN_ID_OUT_OF_BOUNDS","type":"error"},{"inputs":[],"name":"CANNOT_FORWARD_4646_TOKEN","type":"error"},{"inputs":[],"name":"DIFFERENT_TOKENS","type":"error"},{"inputs":[],"name":"DIRECT_DEPOSIT_SWAP_FAILED","type":"error"},{"inputs":[],"name":"DIRECT_WITHDRAW_INVALID_LIQ_REQUEST","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"FAILED_TO_EXECUTE_TXDATA","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT","type":"error"},{"inputs":[],"name":"INSUFFICIENT_BALANCE","type":"error"},{"inputs":[],"name":"INSUFFICIENT_NATIVE_AMOUNT","type":"error"},{"inputs":[],"name":"INVALID_CHAIN_ID","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NOT_CORE_STATE_REGISTRY","type":"error"},{"inputs":[],"name":"NOT_EMERGENCY_QUEUE","type":"error"},{"inputs":[],"name":"NOT_SUPERFORM_ROUTER","type":"error"},{"inputs":[],"name":"NOT_SUPER_REGISTRY","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"PAUSED","type":"error"},{"inputs":[],"name":"SUPERFORM_ID_NONEXISTENT","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"VAULT_IMPLEMENTATION_FAILED","type":"error"},{"inputs":[],"name":"WITHDRAW_TOKEN_NOT_UPDATED","type":"error"},{"inputs":[],"name":"WITHDRAW_TX_DATA_NOT_UPDATED","type":"error"},{"inputs":[],"name":"WITHDRAW_ZERO_COLLATERAL","type":"error"},{"inputs":[],"name":"XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST","type":"error"},{"inputs":[],"name":"ZERO_ADDRESS","type":"error"},{"inputs":[],"name":"ZERO_AMOUNT","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"refundAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EmergencyWithdrawalProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FormDustForwardedToPaymaster","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"srcChainID","type":"uint64"},{"indexed":true,"internalType":"uint64","name":"dstChainId","type":"uint64"},{"indexed":true,"internalType":"uint256","name":"srcPayloadId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"vault","type":"address"}],"name":"Processed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"contract IERC4626","name":"vault","type":"address"}],"name":"VaultAdded","type":"event"},{"inputs":[],"name":"CHAIN_ID","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"payloadId","type":"uint256"},{"internalType":"uint256","name":"superformId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"outputAmount","type":"uint256"},{"internalType":"uint256","name":"maxSlippage","type":"uint256"},{"components":[{"internalType":"bytes","name":"txData","type":"bytes"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"interimToken","type":"address"},{"internalType":"uint8","name":"bridgeId","type":"uint8"},{"internalType":"uint64","name":"liqDstChainId","type":"uint64"},{"internalType":"uint256","name":"nativeAmount","type":"uint256"}],"internalType":"struct LiqRequest","name":"liqData","type":"tuple"},{"internalType":"bool","name":"hasDstSwap","type":"bool"},{"internalType":"bool","name":"retain4626","type":"bool"},{"internalType":"address","name":"receiverAddress","type":"address"},{"internalType":"bytes","name":"extraFormData","type":"bytes"}],"internalType":"struct InitSingleVaultData","name":"singleVaultData_","type":"tuple"},{"internalType":"address","name":"srcSender_","type":"address"}],"name":"directDepositIntoVault","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"payloadId","type":"uint256"},{"internalType":"uint256","name":"superformId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"outputAmount","type":"uint256"},{"internalType":"uint256","name":"maxSlippage","type":"uint256"},{"components":[{"internalType":"bytes","name":"txData","type":"bytes"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"interimToken","type":"address"},{"internalType":"uint8","name":"bridgeId","type":"uint8"},{"internalType":"uint64","name":"liqDstChainId","type":"uint64"},{"internalType":"uint256","name":"nativeAmount","type":"uint256"}],"internalType":"struct LiqRequest","name":"liqData","type":"tuple"},{"internalType":"bool","name":"hasDstSwap","type":"bool"},{"internalType":"bool","name":"retain4626","type":"bool"},{"internalType":"address","name":"receiverAddress","type":"address"},{"internalType":"bytes","name":"extraFormData","type":"bytes"}],"internalType":"struct InitSingleVaultData","name":"singleVaultData_","type":"tuple"},{"internalType":"address","name":"srcSender_","type":"address"}],"name":"directWithdrawFromVault","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiverAddress_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token_","type":"address"}],"name":"forwardDustToPaymaster","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getPreviewPricePerVaultShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPricePerVaultShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStateRegistryId","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVaultAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVaultAsset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVaultDecimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVaultName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVaultShareBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVaultSymbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"superRegistry_","type":"address"},{"internalType":"address","name":"vault_","type":"address"},{"internalType":"address","name":"asset_","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets_","type":"uint256"}],"name":"previewDepositTo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares_","type":"uint256"}],"name":"previewRedeemFrom","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets_","type":"uint256"}],"name":"previewWithdrawFrom","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"superRegistry","outputs":[{"internalType":"contract ISuperRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"superformYieldTokenName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"superformYieldTokenSymbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId_","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"payloadId","type":"uint256"},{"internalType":"uint256","name":"superformId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"outputAmount","type":"uint256"},{"internalType":"uint256","name":"maxSlippage","type":"uint256"},{"components":[{"internalType":"bytes","name":"txData","type":"bytes"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"interimToken","type":"address"},{"internalType":"uint8","name":"bridgeId","type":"uint8"},{"internalType":"uint64","name":"liqDstChainId","type":"uint64"},{"internalType":"uint256","name":"nativeAmount","type":"uint256"}],"internalType":"struct LiqRequest","name":"liqData","type":"tuple"},{"internalType":"bool","name":"hasDstSwap","type":"bool"},{"internalType":"bool","name":"retain4626","type":"bool"},{"internalType":"address","name":"receiverAddress","type":"address"},{"internalType":"bytes","name":"extraFormData","type":"bytes"}],"internalType":"struct InitSingleVaultData","name":"singleVaultData_","type":"tuple"},{"internalType":"address","name":"srcSender_","type":"address"},{"internalType":"uint64","name":"srcChainId_","type":"uint64"}],"name":"xChainDepositIntoVault","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"payloadId","type":"uint256"},{"internalType":"uint256","name":"superformId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"outputAmount","type":"uint256"},{"internalType":"uint256","name":"maxSlippage","type":"uint256"},{"components":[{"internalType":"bytes","name":"txData","type":"bytes"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"interimToken","type":"address"},{"internalType":"uint8","name":"bridgeId","type":"uint8"},{"internalType":"uint64","name":"liqDstChainId","type":"uint64"},{"internalType":"uint256","name":"nativeAmount","type":"uint256"}],"internalType":"struct LiqRequest","name":"liqData","type":"tuple"},{"internalType":"bool","name":"hasDstSwap","type":"bool"},{"internalType":"bool","name":"retain4626","type":"bool"},{"internalType":"address","name":"receiverAddress","type":"address"},{"internalType":"bytes","name":"extraFormData","type":"bytes"}],"internalType":"struct InitSingleVaultData","name":"singleVaultData_","type":"tuple"},{"internalType":"address","name":"srcSender_","type":"address"},{"internalType":"uint64","name":"srcChainId_","type":"uint64"}],"name":"xChainWithdrawFromVault","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
0x60e06040523480156200001157600080fd5b506040516200466f3803806200466f8339810160408190526200003491620001e4565b806001816001600160a01b038116620000605760405163538ba4f960e01b815260040160405180910390fd5b6001600160401b034611156200008957604051637ecdf93360e01b815260040160405180910390fd5b6001600160401b03461660a0526001600160a01b038116608052620000ad62000130565b506080516040516315c80ead60e21b815260ff831660048201526001600160a01b03909116906357203ab490602401602060405180830381865afa158015620000fa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001209190620001e4565b5060ff1660c05250620002169050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff1615620001815760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b0390811614620001e15780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b600060208284031215620001f757600080fd5b81516001600160a01b03811681146200020f57600080fd5b9392505050565b60805160a05160c051614381620002ee60003960006103d601526000818161038801528181610deb0152818161179c015281816122a701526128fb015260008181610268015281816109f101528181610ae501528181610b9c01528181610cd401528181610f1601528181610fcd01528181611105015281816112d3015281816114f4015281816115dd015281816116f50152818161182e01528181611a2e01528181611c1601528181612219015281816124fa015281816127cf01528181612a1d01528181612c140152612e6d01526143816000f3fe6080604052600436106101b75760003560e01c806391deb882116100ec578063c0c53b8b1161008a578063cb829dc311610064578063cb829dc3146104f0578063ef164fef14610510578063fbfa77cf14610530578063ff5f3e481461055057600080fd5b8063c0c53b8b146104a6578063c32dcd89146104c6578063c4e41b22146104db57600080fd5b80639f5376c1116100c65780639f5376c114610440578063b60262ca14610455578063b7ba28cd14610473578063b92327751461049357600080fd5b806391deb882146103c257806395ccea671461040057806395e4f1da1461042057600080fd5b806338d52e0f1161015957806365cacaa41161013357806365cacaa41461032e5780636e07302b1461034c578063771880671461036157806385e1f4d01461037657600080fd5b806338d52e0f146102d757806338d92fd5146102f75780634dcd03c01461030c57600080fd5b806320592d981161019557806320592d981461024157806324c73dda1461025657806335eda680146102a257806337d25010146102b757600080fd5b806301ffc9a7146101bc57806307c080f9146101f157806317a57e081461021f575b600080fd5b3480156101c857600080fd5b506101dc6101d73660046139b1565b610565565b60405190151581526020015b60405180910390f35b3480156101fd57600080fd5b5061021161020c3660046139db565b61059c565b6040519081526020016101e8565b34801561022b57600080fd5b5061023461060b565b6040516101e89190613a44565b34801561024d57600080fd5b506102346106a0565b34801561026257600080fd5b5061028a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101e8565b3480156102ae57600080fd5b50610211610721565b3480156102c357600080fd5b506102116102d23660046139db565b610793565b3480156102e357600080fd5b5060015461028a906001600160a01b031681565b34801561030357600080fd5b506102116107c5565b34801561031857600080fd5b5061032c610327366004613a7c565b6108bc565b005b34801561033a57600080fd5b506000546001600160a01b031661028a565b34801561035857600080fd5b506102116108f7565b34801561036d57600080fd5b5061023461094b565b34801561038257600080fd5b506103aa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160401b0390911681526020016101e8565b3480156103ce57600080fd5b5060405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101e8565b34801561040c57600080fd5b5061032c61041b366004613a99565b6109bc565b34801561042c57600080fd5b5061021161043b366004613d81565b610aa3565b34801561044c57600080fd5b50610234610e59565b34801561046157600080fd5b506001546001600160a01b031661028a565b34801561047f57600080fd5b5061021161048e3660046139db565b610ea2565b6102116104a1366004613de0565b610ed4565b3480156104b257600080fd5b5061032c6104c1366004613e31565b61121a565b3480156104d257600080fd5b506102116113de565b3480156104e757600080fd5b5061021161145e565b3480156104fc57600080fd5b5061021161050b366004613de0565b6114b2565b34801561051c57600080fd5b5061021161052b366004613d81565b6116b3565b34801561053c57600080fd5b5060005461028a906001600160a01b031681565b34801561055c57600080fd5b50610211611906565b60006001600160e01b031982166351fef14760e01b148061059657506301ffc9a760e01b6001600160e01b03198316145b92915050565b600080546040516363737ac960e11b8152600481018490526001600160a01b039091169063c6e6f592906024015b602060405180830381865afa1580156105e7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105969190613e7c565b60008054604080516395d89b4160e01b815290516060936001600160a01b03909316926395d89b4192600480820193918290030181865afa158015610654573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261067c9190810190613e95565b60405160200161068c9190613f02565b604051602081830303815290604052905090565b60008054604080516306fdde0360e01b815290516060936001600160a01b03909316926306fdde0392600480820193918290030181865afa1580156106e9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107119190810190613e95565b60405160200161068c9190613f2d565b600080546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561076a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078e9190613e7c565b905090565b60008054604051630a28a47760e01b8152600481018490526001600160a01b0390911690630a28a477906024016105ca565b600080546040805163313ce56760e01b8152905183926001600160a01b03169163313ce5679160048083019260209291908290030181865afa15801561080f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108339190613f5f565b60005460ff9190911691506001600160a01b0316634cdad50661085783600a614076565b6040518263ffffffff1660e01b815260040161087591815260200190565b602060405180830381865afa158015610892573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b69190613e7c565b91505090565b6000546001600160a01b03908116908216036108eb57604051636ba4485360e01b815260040160405180910390fd5b6108f481611998565b50565b60008060009054906101000a90046001600160a01b03166001600160a01b03166301e1d1146040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076a573d6000803e3d6000fd5b60008054604080516395d89b4160e01b815290516060936001600160a01b03909316926395d89b4192600480820193918290030181865afa158015610994573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261078e9190810190613e95565b6040516321f8a72160e01b81527fa2d83cf6f43caf068994e5ffe0938f6eabaa551d915b59bfda16ba012d30d96860048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa158015610a40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a649190614082565b6001600160a01b0316336001600160a01b031614610a9557604051634a4a4f3160e11b815260040160405180910390fd5b610a9f82826119a1565b5050565b6040516321f8a72160e01b81527f55b101fc856aff484166c46ad33bc74831c135693c159b0092bb3b72254ffb6b600482015260009033906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906321f8a72190602401602060405180830381865afa158015610b2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b509190614082565b6001600160a01b031614610b775760405163460b8af160e11b815260040160405180910390fd5b6040516321f8a72160e01b815260008051602061432c833981519152600482015284907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa158015610beb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0f9190614082565b6001600160a01b031663b5c7569782602001516040518263ffffffff1660e01b8152600401610c4091815260200190565b602060405180830381865afa158015610c5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c81919061409f565b610c9e5760405163a412f06560e01b815260040160405180910390fd5b6000610cad82602001516119ab565b506040516321f8a72160e01b815260008051602061432c83398151915260048201529092507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031691506321f8a72190602401602060405180830381865afa158015610d24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d489190614082565b60405163596db71760e01b815263ffffffff831660048201526001600160a01b03919091169063596db71790602401602060405180830381865afa158015610d94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610db8919061409f565b15610dd657604051632a6ab56360e21b815260040160405180910390fd5b6001600160401b03841615801590610e2057507f00000000000000000000000000000000000000000000000000000000000000006001600160401b0316846001600160401b031614155b15610e3757610e308686866119df565b9250610e50565b60405163030042b760e01b815260040160405180910390fd5b50509392505050565b60008054604080516306fdde0360e01b815290516060936001600160a01b03909316926306fdde0392600480820193918290030181865afa158015610994573d6000803e3d6000fd5b6000805460405163266d6a8360e11b8152600481018490526001600160a01b0390911690634cdad506906024016105ca565b6040516321f8a72160e01b81527f3a2f5529773e03d975be44bdae98a8509bdf1159e407504e558536cde56cf6ac600482015260009033906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906321f8a72190602401602060405180830381865afa158015610f5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f819190614082565b6001600160a01b031614610fa85760405163158a2f6b60e01b815260040160405180910390fd5b6040516321f8a72160e01b815260008051602061432c833981519152600482015283907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa15801561101c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110409190614082565b6001600160a01b031663b5c7569782602001516040518263ffffffff1660e01b815260040161107191815260200190565b602060405180830381865afa15801561108e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b2919061409f565b6110cf5760405163a412f06560e01b815260040160405180910390fd5b60006110de82602001516119ab565b506040516321f8a72160e01b815260008051602061432c83398151915260048201529092507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031691506321f8a72190602401602060405180830381865afa158015611155573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111799190614082565b60405163596db71760e01b815263ffffffff831660048201526001600160a01b03919091169063596db71790602401602060405180830381865afa1580156111c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e9919061409f565b1561120757604051632a6ab56360e21b815260040160405180910390fd5b61121185856119f3565b95945050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b031660008115801561125f5750825b90506000826001600160401b0316600114801561127b5750303b155b905081158015611289575080155b156112a75760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff1916600117855583156112d157845460ff60401b1916600160401b1785555b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316886001600160a01b0316146113235760405163e7b6503f60e01b815260040160405180910390fd5b6001600160a01b038716158061134057506001600160a01b038616155b1561135e5760405163538ba4f960e01b815260040160405180910390fd5b600080546001600160a01b03808a166001600160a01b031992831617909255600180549289169290911691909117905583156113d457845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b60008060009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611432573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114569190613f5f565b60ff16905090565b60008060009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076a573d6000803e3d6000fd5b6040516321f8a72160e01b81527f3a2f5529773e03d975be44bdae98a8509bdf1159e407504e558536cde56cf6ac600482015260009033906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906321f8a72190602401602060405180830381865afa15801561153b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061155f9190614082565b6001600160a01b0316146115865760405163158a2f6b60e01b815260040160405180910390fd5b61159383602001516119fe565b6115a8576115a18383611ba0565b9050610596565b6040516321f8a72160e01b81527fa2d83cf6f43caf068994e5ffe0938f6eabaa551d915b59bfda16ba012d30d96860048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa15801561162c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116509190614082565b6001600160a01b031663bfdf22ad846040518263ffffffff1660e01b815260040161167b9190614129565b600060405180830381600087803b15801561169557600080fd5b505af11580156116a9573d6000803e3d6000fd5b5050505092915050565b6040516321f8a72160e01b81527f55b101fc856aff484166c46ad33bc74831c135693c159b0092bb3b72254ffb6b600482015260009033906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906321f8a72190602401602060405180830381865afa15801561173c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117609190614082565b6001600160a01b0316146117875760405163460b8af160e11b815260040160405180910390fd5b6001600160401b038216158015906117d157507f00000000000000000000000000000000000000000000000000000000000000006001600160401b0316826001600160401b031614155b15610e37576117e384602001516119fe565b6117f9576117f2848484611bab565b90506118ff565b6040516321f8a72160e01b81527fa2d83cf6f43caf068994e5ffe0938f6eabaa551d915b59bfda16ba012d30d96860048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa15801561187d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a19190614082565b6001600160a01b031663bfdf22ad856040518263ffffffff1660e01b81526004016118cc9190614129565b600060405180830381600087803b1580156118e657600080fd5b505af11580156118fa573d6000803e3d6000fd5b505050505b9392505050565b600080546040805163313ce56760e01b8152905183926001600160a01b03169163313ce5679160048083019260209291908290030181865afa158015611950573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119749190613f5f565b60005460ff9190911691506001600160a01b03166307a2d13a61085783600a614076565b6108f481611bb7565b610a9f8282611d52565b8060a081901c60c082901c60008190036119d85760405163030042b760e01b815260040160405180910390fd5b9193909250565b60006119eb8483611e58565b949350505050565b60006118ff83611fcd565b6040516321f8a72160e01b815260008051602061432c833981519152600482015260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906321f8a72190602401602060405180830381865afa158015611a75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a999190614082565b60405163b5c7569760e01b8152600481018590529091506001600160a01b0382169063b5c7569790602401602060405180830381865afa158015611ae1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b05919061409f565b611b225760405163a412f06560e01b815260040160405180910390fd5b6000611b2d846119ab565b5060405163596db71760e01b815263ffffffff821660048201529092506001600160a01b038416915063596db71790602401602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119eb919061409f565b60006118ff83612740565b60006119eb8483612ae8565b6001600160a01b038116611bde5760405163538ba4f960e01b815260040160405180910390fd5b6040516321f8a72160e01b81527fbddfa8c39a1f6275bcfb3aa5c70638c466999edbf14e6162d81b3492caca9fce60048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa158015611c65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c899190614082565b6040516370a0823160e01b815230600482015290915082906000906001600160a01b038316906370a0823190602401602060405180830381865afa158015611cd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf99190613e7c565b90508015611d4c57611d156001600160a01b0383168483612f96565b60405181906001600160a01b038616907fd34222ea8b5b095ec7a6f42ff87fa762ab480b9e8cea464915ee985f1510c10a90600090a35b50505050565b6000546001600160a01b03908116908316611d805760405163538ba4f960e01b815260040160405180910390fd5b6040516370a0823160e01b815230600482015282906001600160a01b038316906370a0823190602401602060405180830381865afa158015611dc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dea9190613e7c565b1015611e0957604051632858f9ab60e11b815260040160405180910390fd5b611e1d6001600160a01b0382168484612f96565b60405182906001600160a01b038516907f83b8068554a495dbb4af07014f8171144d6670eb522b356f8d3f37cbd76ba11690600090a3505050565b600080611e6884602001516119ab565b6000546040888101516001549151636eb1769f60e11b81523360048201523060248201529396506001600160a01b0392831695508594509291169063dd62ed3e90604401602060405180830381865afa158015611ec9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eed9190613e7c565b1015611f0b576040516263c69360e11b815260040160405180910390fd5b6040860151600154611f2c916001600160a01b039091169033903090612ffa565b6040860151600154611f4b916001600160a01b03909116908490613033565b611f5a868288604001516130bd565b93508560000151836001600160401b0316866001600160401b03167f9664a7293fbeac5e42927bc5eb69c82d1fe2f0b17e510b38ebfba582d47923fe896040015186604051611fbc9291909182526001600160a01b0316602082015260400190565b60405180910390a450505092915050565b600061204060405180610140016040528060006001600160401b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001606081525090565b6000546001546001600160a01b03908116602084018190526040516370a0823160e01b81523060048201529190921691906370a0823190602401602060405180830381865afa158015612097573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120bb9190613e7c565b608083015260a0840151602001516001600160a01b03811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906120fa575060a08501515151155b156121eb5782602001516001600160a01b03168560a00151602001516001600160a01b03161461213d576040516310ac1a6760e31b815260040160405180910390fd5b6040858101519051636eb1769f60e11b81523360048201523060248201526001600160a01b0383169063dd62ed3e90604401602060405180830381865afa15801561218c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b09190613e7c565b10156121ce576040516263c69360e11b815260040160405180910390fd5b60408501516121eb906001600160a01b0383169033903090612ffa565b60a08501515151156126395760a085015160600151604051633a16cad560e21b815260ff90911660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e85b2b5490602401602060405180830381865afa158015612268573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061228c9190614082565b6001600160a01b031660408085018290526001600160401b037f000000000000000000000000000000000000000000000000000000000000000016855260a087015151905163137776b960e31b8152639bbbb5c8916122f0916000906004016141db565b602060405180830381865afa15801561230d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123319190613e7c565b6101008401526001600160a01b03811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1461240b57610100830151604051636eb1769f60e11b81523360048201523060248201526001600160a01b0383169063dd62ed3e90604401602060405180830381865afa1580156123ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123cf9190613e7c565b10156123ed576040516263c69360e11b815260040160405180910390fd5b61010083015161240b906001600160a01b0383169033903090612ffa565b60408084015181516101208101835260a08089015151825286516001600160401b039081166020840152875181168386015287511660608301526001608083015230908201523360c08201526001600160a01b0384811660e08301526000610100830152925163c87439eb60e01b8152929091169163c87439eb91612492916004016141ff565b602060405180830381865afa1580156124af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124d3919061409f565b5060a08501516060015160405163ca7adffb60e01b815260ff909116600482015261258b907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ca7adffb90602401602060405180830381865afa158015612549573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061256d9190614082565b8660a0015160000151838661010001518960a0015160a00151613298565b82602001516001600160a01b031683604001516001600160a01b0316632db883238760a00151600001516040518263ffffffff1660e01b81526004016125d19190613a44565b602060405180830381865afa1580156125ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126129190614082565b6001600160a01b031614612639576040516310ac1a6760e31b815260040160405180910390fd5b608083015160208401516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015612688573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126ac9190613e7c565b6126b691906142d2565b60a084015260808501516126cc906127106142d2565b85604001516126db91906142e5565b6127108460a001516126ed91906142e5565b101561270c57604051630edf4d2360e01b815260040160405180910390fd5b60005460a08401516020850151612731926001600160a01b0391821692911690613033565b61121185838560a001516130bd565b604080516080810182526000808252602082018190529181018290526060810182905260005460015460e08501516001600160a01b039283169290911690612ab6576001546001600160a01b0316602084015261279e8583836134ac565b60a0860151515190945015612ab15760a085015160600151604051633a16cad560e21b815260ff90911660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e85b2b5490602401602060405180830381865afa15801561281e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128429190614082565b6001600160a01b0316604080850182905260a087015151905163137776b960e31b8152639bbbb5c89161287a916000906004016141db565b602060405180830381865afa158015612897573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128bb9190613e7c565b6060840181905260808601516128d3919086906136af565b156128f1576040516308d6a07f60e21b815260040160405180910390fd5b6001600160401b037f00000000000000000000000000000000000000000000000000000000000000008116845260408085015181516101208101835260a0808a0180515183528851861660208085019190915289518716848701529051608090810151909616606084015260009583018690523091830191909152610100808b01516001600160a01b0390811660c085015291890151821660e0840152820194909452915163c87439eb60e01b815292169163c87439eb916129b5916004016141ff565b602060405180830381865afa1580156129d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129f6919061409f565b5060a08501516060015160405163ca7adffb60e01b815260ff9091166004820152612ab1907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ca7adffb90602401602060405180830381865afa158015612a6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a909190614082565b8660a0015160000151856020015186606001518960a0015160a00151613298565b612ae0565b6101008501516040860151612ad5916001600160a01b03851691612f96565b506000949350505050565b505050919050565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260a08401518051516020909101516001600160a01b031615801590612b3c575080155b15612b5957604051628f1a5560e71b815260040160405180910390fd5b60a0850151602001516001600160a01b0316158015612b7757508015155b15612b955760405163a9644b6760e01b815260040160405180910390fd5b612ba285602001516119ab565b6001600160401b03168452505060005460015460e08701516001600160a01b039283169290911690612f06576001546001600160a01b03166020850152612bea8783836134ac565b94508215612f015760a087015160600151604051633a16cad560e21b815260ff90911660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e85b2b5490602401602060405180830381865afa158015612c63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c879190614082565b6001600160a01b0316604080860182905260a089015151905163137776b960e31b8152639bbbb5c891612cbf916000906004016141db565b602060405180830381865afa158015612cdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d009190613e7c565b60a085018190526080880151612d18919087906136af565b15612d3657604051636cbab5a560e01b815260040160405180910390fd5b83604001516001600160a01b031663c87439eb6040518061012001604052808a60a0015160000151815260200187600001516001600160401b03168152602001896001600160401b031681526020018a60a00151608001516001600160401b03168152602001600015158152602001306001600160a01b031681526020018a61010001516001600160a01b0316815260200187602001516001600160a01b0316815260200160006001600160a01b03168152506040518263ffffffff1660e01b8152600401612e0591906141ff565b602060405180830381865afa158015612e22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e46919061409f565b5060a08701516060015160405163ca7adffb60e01b815260ff9091166004820152612f01907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ca7adffb90602401602060405180830381865afa158015612ebc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ee09190614082565b8860a001516000015186602001518760a001518b60a0015160a00151613298565b612f32565b6101008701516040880151612f25916001600160a01b03851691612f96565b6000945050505050610596565b865184516040808a015160005482519182526001600160a01b031660208201526001600160401b03928316928a16917f9664a7293fbeac5e42927bc5eb69c82d1fe2f0b17e510b38ebfba582d47923fe910160405180910390a45050505092915050565b6040516001600160a01b03838116602483015260448201839052612ff591859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506136eb565b505050565b6040516001600160a01b038481166024830152838116604483015260648201839052611d4c9186918216906323b872dd90608401612fc3565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015613083573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130a79190613e7c565b9050611d4c84846130b885856142fc565b61374e565b6000808460e001516130cf57306130d6565b8461010001515b6040516370a0823160e01b81526001600160a01b0380831660048301529192506000918616906370a0823190602401602060405180830381865afa158015613122573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131469190613e7c565b604051636e553f6560e01b8152600481018690526001600160a01b03848116602483015291925090861690636e553f65906044016020604051808303816000875af1158015613199573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131bd9190613e7c565b6040516370a0823160e01b81526001600160a01b0384811660048301529194506000918716906370a0823190602401602060405180830381865afa158015613209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061322d9190613e7c565b90508361323a83836142d2565b14158061327057506080870151613253906127106142d2565b876060015161326291906142e5565b61326e856127106142e5565b105b1561328e57604051635ebf8da160e11b815260040160405180910390fd5b5050509392505050565b816000036132b957604051630f6fa54560e41b815260040160405180910390fd5b6001600160a01b0385166132e05760405163538ba4f960e01b815260040160405180910390fd5b6001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1461331d576133186001600160a01b0384168684613033565b61335f565b8181101561333e5760405163e4f2466360e01b815260040160405180910390fd5b4781111561335f57604051632858f9ab60e11b815260040160405180910390fd5b6000856001600160a01b0316828660405161337a919061430f565b60006040518083038185875af1925050503d80600081146133b7576040519150601f19603f3d011682016040523d82523d6000602084013e6133bc565b606091505b50509050806133ee57604051632accaa1560e01b81526001600160a01b03851660048201526024015b60405180910390fd5b6001600160a01b03841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146134a457604051636eb1769f60e11b81523060048201526001600160a01b038781166024830152859160009183169063dd62ed3e90604401602060405180830381865afa158015613463573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134879190613e7c565b11156134a2576134a26001600160a01b03821688600061374e565b505b505050505050565b60a083015151516000908190156134c357306134ca565b8461010001515b6040516370a0823160e01b81526001600160a01b0380831660048301529192506000918516906370a0823190602401602060405180830381865afa158015613516573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353a9190613e7c565b6040878101519051635d043b2960e11b815260048101919091526001600160a01b0384811660248301523060448301529192509086169063ba087652906064016020604051808303816000875af1158015613599573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135bd9190613e7c565b6040516370a0823160e01b81526001600160a01b0384811660048301529194506000918616906370a0823190602401602060405180830381865afa158015613609573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061362d9190613e7c565b90508361363a83836142d2565b14158061367057506080870151613653906127106142d2565b876060015161366291906142e5565b61366e856127106142e5565b105b1561368e57604051635ebf8da160e11b815260040160405180910390fd5b8360000361328e5760405163affdc82f60e01b815260040160405180910390fd5b6000828411806136de57506136c6826127106142d2565b6136d090846142e5565b6136dc612710866142e5565b105b156118ff575060016118ff565b60006137006001600160a01b038416836137de565b90508051600014158015613725575080806020019051810190613723919061409f565b155b15612ff557604051635274afe760e01b81526001600160a01b03841660048201526024016133e5565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261379f84826137ec565b611d4c576040516001600160a01b038481166024830152600060448301526137d491869182169063095ea7b390606401612fc3565b611d4c84826136eb565b60606118ff8383600061388f565b6000806000846001600160a01b031684604051613809919061430f565b6000604051808303816000865af19150503d8060008114613846576040519150601f19603f3d011682016040523d82523d6000602084013e61384b565b606091505b5091509150818015613875575080511580613875575080806020019051810190613875919061409f565b80156112115750505050506001600160a01b03163b151590565b6060814710156138b45760405163cd78605960e01b81523060048201526024016133e5565b600080856001600160a01b031684866040516138d0919061430f565b60006040518083038185875af1925050503d806000811461390d576040519150601f19603f3d011682016040523d82523d6000602084013e613912565b606091505b509150915061392286838361392c565b9695505050505050565b6060826139415761393c82613988565b6118ff565b815115801561395857506001600160a01b0384163b155b1561398157604051639996b31560e01b81526001600160a01b03851660048201526024016133e5565b50806118ff565b8051156139985780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6000602082840312156139c357600080fd5b81356001600160e01b0319811681146118ff57600080fd5b6000602082840312156139ed57600080fd5b5035919050565b60005b83811015613a0f5781810151838201526020016139f7565b50506000910152565b60008151808452613a308160208601602086016139f4565b601f01601f19169290920160200192915050565b6020815260006118ff6020830184613a18565b6001600160a01b03811681146108f457600080fd5b8035613a7781613a57565b919050565b600060208284031215613a8e57600080fd5b81356118ff81613a57565b60008060408385031215613aac57600080fd5b8235613ab781613a57565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b60405161014081016001600160401b0381118282101715613afe57613afe613ac5565b60405290565b604051601f8201601f191681016001600160401b0381118282101715613b2c57613b2c613ac5565b604052919050565b60006001600160401b03821115613b4d57613b4d613ac5565b50601f01601f191660200190565b600082601f830112613b6c57600080fd5b8135613b7f613b7a82613b34565b613b04565b818152846020838601011115613b9457600080fd5b816020850160208301376000918101602001919091529392505050565b60ff811681146108f457600080fd5b80356001600160401b0381168114613a7757600080fd5b600060c08284031215613be957600080fd5b60405160c081016001600160401b038282108183111715613c0c57613c0c613ac5565b816040528293508435915080821115613c2457600080fd5b50613c3185828601613b5b565b8252506020830135613c4281613a57565b60208201526040830135613c5581613a57565b60408201526060830135613c6881613bb1565b6060820152613c7960808401613bc0565b608082015260a083013560a08201525092915050565b80151581146108f457600080fd5b8035613a7781613c8f565b60006101408284031215613cbb57600080fd5b613cc3613adb565b9050813581526020820135602082015260408201356040820152606082013560608201526080820135608082015260a08201356001600160401b0380821115613d0b57600080fd5b613d1785838601613bd7565b60a0840152613d2860c08501613c9d565b60c0840152613d3960e08501613c9d565b60e08401526101009150613d4e828501613a6c565b8284015261012091508184013581811115613d6857600080fd5b613d7486828701613b5b565b8385015250505092915050565b600080600060608486031215613d9657600080fd5b83356001600160401b03811115613dac57600080fd5b613db886828701613ca8565b9350506020840135613dc981613a57565b9150613dd760408501613bc0565b90509250925092565b60008060408385031215613df357600080fd5b82356001600160401b03811115613e0957600080fd5b613e1585828601613ca8565b9250506020830135613e2681613a57565b809150509250929050565b600080600060608486031215613e4657600080fd5b8335613e5181613a57565b92506020840135613e6181613a57565b91506040840135613e7181613a57565b809150509250925092565b600060208284031215613e8e57600080fd5b5051919050565b600060208284031215613ea757600080fd5b81516001600160401b03811115613ebd57600080fd5b8201601f81018413613ece57600080fd5b8051613edc613b7a82613b34565b818152856020838501011115613ef157600080fd5b6112118260208301602086016139f4565b6273702d60e81b815260008251613f208160038501602087016139f4565b9190910160030192915050565b60008251613f3f8184602087016139f4565b6d1029bab832b92837b9b4ba34b7b760911b920191825250600e01919050565b600060208284031215613f7157600080fd5b81516118ff81613bb1565b634e487b7160e01b600052601160045260246000fd5b600181815b80851115613fcd578160001904821115613fb357613fb3613f7c565b80851615613fc057918102915b93841c9390800290613f97565b509250929050565b600082613fe457506001610596565b81613ff157506000610596565b816001811461400757600281146140115761402d565b6001915050610596565b60ff84111561402257614022613f7c565b50506001821b610596565b5060208310610133831016604e8410600b8410161715614050575081810a610596565b61405a8383613f92565b806000190482111561406e5761406e613f7c565b029392505050565b60006118ff8383613fd5565b60006020828403121561409457600080fd5b81516118ff81613a57565b6000602082840312156140b157600080fd5b81516118ff81613c8f565b6000815160c084526140d160c0850182613a18565b9050602083015160018060a01b038082166020870152806040860151166040870152505060ff60608401511660608501526001600160401b03608084015116608085015260a083015160a08501528091505092915050565b6020815281516020820152602082015160408201526040820151606082015260608201516080820152608082015160a0820152600060a08301516101408060c085015261417a6101608501836140bc565b915060c085015161418f60e086018215159052565b5060e08501516101006141a58187018315159052565b86015190506101206141c1868201836001600160a01b03169052565b860151858403601f19018387015290506139228382613a18565b6040815260006141ee6040830185613a18565b905082151560208301529392505050565b602081526000825161012080602085015261421e610140850183613a18565b9150602085015161423a60408601826001600160401b03169052565b5060408501516001600160401b03811660608601525060608501516001600160401b038116608086015250608085015180151560a08601525060a08501516001600160a01b03811660c08601525060c08501516001600160a01b03811660e08601525060e08501516101006142b9818701836001600160a01b03169052565b909501516001600160a01b031693019290925250919050565b8181038181111561059657610596613f7c565b808202811582820484141761059657610596613f7c565b8082018082111561059657610596613f7c565b600082516143218184602087016139f4565b919091019291505056febcc180fb907e9ae431665de4bc74305c00b7b27442aadd477980ecc4bb14c011a26469706673582212200df59e65970b93b00d3113e859b9be5fafbc8485500f9eb2f1750a64a2579cfb64736f6c6343000817003300000000000000000000000017a332dc7b40ae701485023b219e9d6f493a2514
Deployed Bytecode
0x6080604052600436106101b75760003560e01c806391deb882116100ec578063c0c53b8b1161008a578063cb829dc311610064578063cb829dc3146104f0578063ef164fef14610510578063fbfa77cf14610530578063ff5f3e481461055057600080fd5b8063c0c53b8b146104a6578063c32dcd89146104c6578063c4e41b22146104db57600080fd5b80639f5376c1116100c65780639f5376c114610440578063b60262ca14610455578063b7ba28cd14610473578063b92327751461049357600080fd5b806391deb882146103c257806395ccea671461040057806395e4f1da1461042057600080fd5b806338d52e0f1161015957806365cacaa41161013357806365cacaa41461032e5780636e07302b1461034c578063771880671461036157806385e1f4d01461037657600080fd5b806338d52e0f146102d757806338d92fd5146102f75780634dcd03c01461030c57600080fd5b806320592d981161019557806320592d981461024157806324c73dda1461025657806335eda680146102a257806337d25010146102b757600080fd5b806301ffc9a7146101bc57806307c080f9146101f157806317a57e081461021f575b600080fd5b3480156101c857600080fd5b506101dc6101d73660046139b1565b610565565b60405190151581526020015b60405180910390f35b3480156101fd57600080fd5b5061021161020c3660046139db565b61059c565b6040519081526020016101e8565b34801561022b57600080fd5b5061023461060b565b6040516101e89190613a44565b34801561024d57600080fd5b506102346106a0565b34801561026257600080fd5b5061028a7f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a251481565b6040516001600160a01b0390911681526020016101e8565b3480156102ae57600080fd5b50610211610721565b3480156102c357600080fd5b506102116102d23660046139db565b610793565b3480156102e357600080fd5b5060015461028a906001600160a01b031681565b34801561030357600080fd5b506102116107c5565b34801561031857600080fd5b5061032c610327366004613a7c565b6108bc565b005b34801561033a57600080fd5b506000546001600160a01b031661028a565b34801561035857600080fd5b506102116108f7565b34801561036d57600080fd5b5061023461094b565b34801561038257600080fd5b506103aa7f000000000000000000000000000000000000000000000000000000000000e70881565b6040516001600160401b0390911681526020016101e8565b3480156103ce57600080fd5b5060405160ff7f00000000000000000000000000000000000000000000000000000000000000011681526020016101e8565b34801561040c57600080fd5b5061032c61041b366004613a99565b6109bc565b34801561042c57600080fd5b5061021161043b366004613d81565b610aa3565b34801561044c57600080fd5b50610234610e59565b34801561046157600080fd5b506001546001600160a01b031661028a565b34801561047f57600080fd5b5061021161048e3660046139db565b610ea2565b6102116104a1366004613de0565b610ed4565b3480156104b257600080fd5b5061032c6104c1366004613e31565b61121a565b3480156104d257600080fd5b506102116113de565b3480156104e757600080fd5b5061021161145e565b3480156104fc57600080fd5b5061021161050b366004613de0565b6114b2565b34801561051c57600080fd5b5061021161052b366004613d81565b6116b3565b34801561053c57600080fd5b5060005461028a906001600160a01b031681565b34801561055c57600080fd5b50610211611906565b60006001600160e01b031982166351fef14760e01b148061059657506301ffc9a760e01b6001600160e01b03198316145b92915050565b600080546040516363737ac960e11b8152600481018490526001600160a01b039091169063c6e6f592906024015b602060405180830381865afa1580156105e7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105969190613e7c565b60008054604080516395d89b4160e01b815290516060936001600160a01b03909316926395d89b4192600480820193918290030181865afa158015610654573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261067c9190810190613e95565b60405160200161068c9190613f02565b604051602081830303815290604052905090565b60008054604080516306fdde0360e01b815290516060936001600160a01b03909316926306fdde0392600480820193918290030181865afa1580156106e9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107119190810190613e95565b60405160200161068c9190613f2d565b600080546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561076a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078e9190613e7c565b905090565b60008054604051630a28a47760e01b8152600481018490526001600160a01b0390911690630a28a477906024016105ca565b600080546040805163313ce56760e01b8152905183926001600160a01b03169163313ce5679160048083019260209291908290030181865afa15801561080f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108339190613f5f565b60005460ff9190911691506001600160a01b0316634cdad50661085783600a614076565b6040518263ffffffff1660e01b815260040161087591815260200190565b602060405180830381865afa158015610892573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b69190613e7c565b91505090565b6000546001600160a01b03908116908216036108eb57604051636ba4485360e01b815260040160405180910390fd5b6108f481611998565b50565b60008060009054906101000a90046001600160a01b03166001600160a01b03166301e1d1146040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076a573d6000803e3d6000fd5b60008054604080516395d89b4160e01b815290516060936001600160a01b03909316926395d89b4192600480820193918290030181865afa158015610994573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261078e9190810190613e95565b6040516321f8a72160e01b81527fa2d83cf6f43caf068994e5ffe0938f6eabaa551d915b59bfda16ba012d30d96860048201527f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa158015610a40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a649190614082565b6001600160a01b0316336001600160a01b031614610a9557604051634a4a4f3160e11b815260040160405180910390fd5b610a9f82826119a1565b5050565b6040516321f8a72160e01b81527f55b101fc856aff484166c46ad33bc74831c135693c159b0092bb3b72254ffb6b600482015260009033906001600160a01b037f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a251416906321f8a72190602401602060405180830381865afa158015610b2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b509190614082565b6001600160a01b031614610b775760405163460b8af160e11b815260040160405180910390fd5b6040516321f8a72160e01b815260008051602061432c833981519152600482015284907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa158015610beb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0f9190614082565b6001600160a01b031663b5c7569782602001516040518263ffffffff1660e01b8152600401610c4091815260200190565b602060405180830381865afa158015610c5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c81919061409f565b610c9e5760405163a412f06560e01b815260040160405180910390fd5b6000610cad82602001516119ab565b506040516321f8a72160e01b815260008051602061432c83398151915260048201529092507f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b031691506321f8a72190602401602060405180830381865afa158015610d24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d489190614082565b60405163596db71760e01b815263ffffffff831660048201526001600160a01b03919091169063596db71790602401602060405180830381865afa158015610d94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610db8919061409f565b15610dd657604051632a6ab56360e21b815260040160405180910390fd5b6001600160401b03841615801590610e2057507f000000000000000000000000000000000000000000000000000000000000e7086001600160401b0316846001600160401b031614155b15610e3757610e308686866119df565b9250610e50565b60405163030042b760e01b815260040160405180910390fd5b50509392505050565b60008054604080516306fdde0360e01b815290516060936001600160a01b03909316926306fdde0392600480820193918290030181865afa158015610994573d6000803e3d6000fd5b6000805460405163266d6a8360e11b8152600481018490526001600160a01b0390911690634cdad506906024016105ca565b6040516321f8a72160e01b81527f3a2f5529773e03d975be44bdae98a8509bdf1159e407504e558536cde56cf6ac600482015260009033906001600160a01b037f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a251416906321f8a72190602401602060405180830381865afa158015610f5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f819190614082565b6001600160a01b031614610fa85760405163158a2f6b60e01b815260040160405180910390fd5b6040516321f8a72160e01b815260008051602061432c833981519152600482015283907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa15801561101c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110409190614082565b6001600160a01b031663b5c7569782602001516040518263ffffffff1660e01b815260040161107191815260200190565b602060405180830381865afa15801561108e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b2919061409f565b6110cf5760405163a412f06560e01b815260040160405180910390fd5b60006110de82602001516119ab565b506040516321f8a72160e01b815260008051602061432c83398151915260048201529092507f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b031691506321f8a72190602401602060405180830381865afa158015611155573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111799190614082565b60405163596db71760e01b815263ffffffff831660048201526001600160a01b03919091169063596db71790602401602060405180830381865afa1580156111c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e9919061409f565b1561120757604051632a6ab56360e21b815260040160405180910390fd5b61121185856119f3565b95945050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b031660008115801561125f5750825b90506000826001600160401b0316600114801561127b5750303b155b905081158015611289575080155b156112a75760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff1916600117855583156112d157845460ff60401b1916600160401b1785555b7f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316886001600160a01b0316146113235760405163e7b6503f60e01b815260040160405180910390fd5b6001600160a01b038716158061134057506001600160a01b038616155b1561135e5760405163538ba4f960e01b815260040160405180910390fd5b600080546001600160a01b03808a166001600160a01b031992831617909255600180549289169290911691909117905583156113d457845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b60008060009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611432573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114569190613f5f565b60ff16905090565b60008060009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561076a573d6000803e3d6000fd5b6040516321f8a72160e01b81527f3a2f5529773e03d975be44bdae98a8509bdf1159e407504e558536cde56cf6ac600482015260009033906001600160a01b037f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a251416906321f8a72190602401602060405180830381865afa15801561153b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061155f9190614082565b6001600160a01b0316146115865760405163158a2f6b60e01b815260040160405180910390fd5b61159383602001516119fe565b6115a8576115a18383611ba0565b9050610596565b6040516321f8a72160e01b81527fa2d83cf6f43caf068994e5ffe0938f6eabaa551d915b59bfda16ba012d30d96860048201527f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa15801561162c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116509190614082565b6001600160a01b031663bfdf22ad846040518263ffffffff1660e01b815260040161167b9190614129565b600060405180830381600087803b15801561169557600080fd5b505af11580156116a9573d6000803e3d6000fd5b5050505092915050565b6040516321f8a72160e01b81527f55b101fc856aff484166c46ad33bc74831c135693c159b0092bb3b72254ffb6b600482015260009033906001600160a01b037f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a251416906321f8a72190602401602060405180830381865afa15801561173c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117609190614082565b6001600160a01b0316146117875760405163460b8af160e11b815260040160405180910390fd5b6001600160401b038216158015906117d157507f000000000000000000000000000000000000000000000000000000000000e7086001600160401b0316826001600160401b031614155b15610e37576117e384602001516119fe565b6117f9576117f2848484611bab565b90506118ff565b6040516321f8a72160e01b81527fa2d83cf6f43caf068994e5ffe0938f6eabaa551d915b59bfda16ba012d30d96860048201527f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa15801561187d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a19190614082565b6001600160a01b031663bfdf22ad856040518263ffffffff1660e01b81526004016118cc9190614129565b600060405180830381600087803b1580156118e657600080fd5b505af11580156118fa573d6000803e3d6000fd5b505050505b9392505050565b600080546040805163313ce56760e01b8152905183926001600160a01b03169163313ce5679160048083019260209291908290030181865afa158015611950573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119749190613f5f565b60005460ff9190911691506001600160a01b03166307a2d13a61085783600a614076565b6108f481611bb7565b610a9f8282611d52565b8060a081901c60c082901c60008190036119d85760405163030042b760e01b815260040160405180910390fd5b9193909250565b60006119eb8483611e58565b949350505050565b60006118ff83611fcd565b6040516321f8a72160e01b815260008051602061432c833981519152600482015260009081906001600160a01b037f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a251416906321f8a72190602401602060405180830381865afa158015611a75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a999190614082565b60405163b5c7569760e01b8152600481018590529091506001600160a01b0382169063b5c7569790602401602060405180830381865afa158015611ae1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b05919061409f565b611b225760405163a412f06560e01b815260040160405180910390fd5b6000611b2d846119ab565b5060405163596db71760e01b815263ffffffff821660048201529092506001600160a01b038416915063596db71790602401602060405180830381865afa158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119eb919061409f565b60006118ff83612740565b60006119eb8483612ae8565b6001600160a01b038116611bde5760405163538ba4f960e01b815260040160405180910390fd5b6040516321f8a72160e01b81527fbddfa8c39a1f6275bcfb3aa5c70638c466999edbf14e6162d81b3492caca9fce60048201526000907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa158015611c65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c899190614082565b6040516370a0823160e01b815230600482015290915082906000906001600160a01b038316906370a0823190602401602060405180830381865afa158015611cd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf99190613e7c565b90508015611d4c57611d156001600160a01b0383168483612f96565b60405181906001600160a01b038616907fd34222ea8b5b095ec7a6f42ff87fa762ab480b9e8cea464915ee985f1510c10a90600090a35b50505050565b6000546001600160a01b03908116908316611d805760405163538ba4f960e01b815260040160405180910390fd5b6040516370a0823160e01b815230600482015282906001600160a01b038316906370a0823190602401602060405180830381865afa158015611dc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dea9190613e7c565b1015611e0957604051632858f9ab60e11b815260040160405180910390fd5b611e1d6001600160a01b0382168484612f96565b60405182906001600160a01b038516907f83b8068554a495dbb4af07014f8171144d6670eb522b356f8d3f37cbd76ba11690600090a3505050565b600080611e6884602001516119ab565b6000546040888101516001549151636eb1769f60e11b81523360048201523060248201529396506001600160a01b0392831695508594509291169063dd62ed3e90604401602060405180830381865afa158015611ec9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eed9190613e7c565b1015611f0b576040516263c69360e11b815260040160405180910390fd5b6040860151600154611f2c916001600160a01b039091169033903090612ffa565b6040860151600154611f4b916001600160a01b03909116908490613033565b611f5a868288604001516130bd565b93508560000151836001600160401b0316866001600160401b03167f9664a7293fbeac5e42927bc5eb69c82d1fe2f0b17e510b38ebfba582d47923fe896040015186604051611fbc9291909182526001600160a01b0316602082015260400190565b60405180910390a450505092915050565b600061204060405180610140016040528060006001600160401b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001606081525090565b6000546001546001600160a01b03908116602084018190526040516370a0823160e01b81523060048201529190921691906370a0823190602401602060405180830381865afa158015612097573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120bb9190613e7c565b608083015260a0840151602001516001600160a01b03811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906120fa575060a08501515151155b156121eb5782602001516001600160a01b03168560a00151602001516001600160a01b03161461213d576040516310ac1a6760e31b815260040160405180910390fd5b6040858101519051636eb1769f60e11b81523360048201523060248201526001600160a01b0383169063dd62ed3e90604401602060405180830381865afa15801561218c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b09190613e7c565b10156121ce576040516263c69360e11b815260040160405180910390fd5b60408501516121eb906001600160a01b0383169033903090612ffa565b60a08501515151156126395760a085015160600151604051633a16cad560e21b815260ff90911660048201527f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b03169063e85b2b5490602401602060405180830381865afa158015612268573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061228c9190614082565b6001600160a01b031660408085018290526001600160401b037f000000000000000000000000000000000000000000000000000000000000e70816855260a087015151905163137776b960e31b8152639bbbb5c8916122f0916000906004016141db565b602060405180830381865afa15801561230d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123319190613e7c565b6101008401526001600160a01b03811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1461240b57610100830151604051636eb1769f60e11b81523360048201523060248201526001600160a01b0383169063dd62ed3e90604401602060405180830381865afa1580156123ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123cf9190613e7c565b10156123ed576040516263c69360e11b815260040160405180910390fd5b61010083015161240b906001600160a01b0383169033903090612ffa565b60408084015181516101208101835260a08089015151825286516001600160401b039081166020840152875181168386015287511660608301526001608083015230908201523360c08201526001600160a01b0384811660e08301526000610100830152925163c87439eb60e01b8152929091169163c87439eb91612492916004016141ff565b602060405180830381865afa1580156124af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124d3919061409f565b5060a08501516060015160405163ca7adffb60e01b815260ff909116600482015261258b907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b03169063ca7adffb90602401602060405180830381865afa158015612549573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061256d9190614082565b8660a0015160000151838661010001518960a0015160a00151613298565b82602001516001600160a01b031683604001516001600160a01b0316632db883238760a00151600001516040518263ffffffff1660e01b81526004016125d19190613a44565b602060405180830381865afa1580156125ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126129190614082565b6001600160a01b031614612639576040516310ac1a6760e31b815260040160405180910390fd5b608083015160208401516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015612688573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126ac9190613e7c565b6126b691906142d2565b60a084015260808501516126cc906127106142d2565b85604001516126db91906142e5565b6127108460a001516126ed91906142e5565b101561270c57604051630edf4d2360e01b815260040160405180910390fd5b60005460a08401516020850151612731926001600160a01b0391821692911690613033565b61121185838560a001516130bd565b604080516080810182526000808252602082018190529181018290526060810182905260005460015460e08501516001600160a01b039283169290911690612ab6576001546001600160a01b0316602084015261279e8583836134ac565b60a0860151515190945015612ab15760a085015160600151604051633a16cad560e21b815260ff90911660048201527f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b03169063e85b2b5490602401602060405180830381865afa15801561281e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128429190614082565b6001600160a01b0316604080850182905260a087015151905163137776b960e31b8152639bbbb5c89161287a916000906004016141db565b602060405180830381865afa158015612897573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128bb9190613e7c565b6060840181905260808601516128d3919086906136af565b156128f1576040516308d6a07f60e21b815260040160405180910390fd5b6001600160401b037f000000000000000000000000000000000000000000000000000000000000e7088116845260408085015181516101208101835260a0808a0180515183528851861660208085019190915289518716848701529051608090810151909616606084015260009583018690523091830191909152610100808b01516001600160a01b0390811660c085015291890151821660e0840152820194909452915163c87439eb60e01b815292169163c87439eb916129b5916004016141ff565b602060405180830381865afa1580156129d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129f6919061409f565b5060a08501516060015160405163ca7adffb60e01b815260ff9091166004820152612ab1907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b03169063ca7adffb90602401602060405180830381865afa158015612a6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a909190614082565b8660a0015160000151856020015186606001518960a0015160a00151613298565b612ae0565b6101008501516040860151612ad5916001600160a01b03851691612f96565b506000949350505050565b505050919050565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260a08401518051516020909101516001600160a01b031615801590612b3c575080155b15612b5957604051628f1a5560e71b815260040160405180910390fd5b60a0850151602001516001600160a01b0316158015612b7757508015155b15612b955760405163a9644b6760e01b815260040160405180910390fd5b612ba285602001516119ab565b6001600160401b03168452505060005460015460e08701516001600160a01b039283169290911690612f06576001546001600160a01b03166020850152612bea8783836134ac565b94508215612f015760a087015160600151604051633a16cad560e21b815260ff90911660048201527f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b03169063e85b2b5490602401602060405180830381865afa158015612c63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c879190614082565b6001600160a01b0316604080860182905260a089015151905163137776b960e31b8152639bbbb5c891612cbf916000906004016141db565b602060405180830381865afa158015612cdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d009190613e7c565b60a085018190526080880151612d18919087906136af565b15612d3657604051636cbab5a560e01b815260040160405180910390fd5b83604001516001600160a01b031663c87439eb6040518061012001604052808a60a0015160000151815260200187600001516001600160401b03168152602001896001600160401b031681526020018a60a00151608001516001600160401b03168152602001600015158152602001306001600160a01b031681526020018a61010001516001600160a01b0316815260200187602001516001600160a01b0316815260200160006001600160a01b03168152506040518263ffffffff1660e01b8152600401612e0591906141ff565b602060405180830381865afa158015612e22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e46919061409f565b5060a08701516060015160405163ca7adffb60e01b815260ff9091166004820152612f01907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b03169063ca7adffb90602401602060405180830381865afa158015612ebc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ee09190614082565b8860a001516000015186602001518760a001518b60a0015160a00151613298565b612f32565b6101008701516040880151612f25916001600160a01b03851691612f96565b6000945050505050610596565b865184516040808a015160005482519182526001600160a01b031660208201526001600160401b03928316928a16917f9664a7293fbeac5e42927bc5eb69c82d1fe2f0b17e510b38ebfba582d47923fe910160405180910390a45050505092915050565b6040516001600160a01b03838116602483015260448201839052612ff591859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506136eb565b505050565b6040516001600160a01b038481166024830152838116604483015260648201839052611d4c9186918216906323b872dd90608401612fc3565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015613083573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130a79190613e7c565b9050611d4c84846130b885856142fc565b61374e565b6000808460e001516130cf57306130d6565b8461010001515b6040516370a0823160e01b81526001600160a01b0380831660048301529192506000918616906370a0823190602401602060405180830381865afa158015613122573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131469190613e7c565b604051636e553f6560e01b8152600481018690526001600160a01b03848116602483015291925090861690636e553f65906044016020604051808303816000875af1158015613199573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131bd9190613e7c565b6040516370a0823160e01b81526001600160a01b0384811660048301529194506000918716906370a0823190602401602060405180830381865afa158015613209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061322d9190613e7c565b90508361323a83836142d2565b14158061327057506080870151613253906127106142d2565b876060015161326291906142e5565b61326e856127106142e5565b105b1561328e57604051635ebf8da160e11b815260040160405180910390fd5b5050509392505050565b816000036132b957604051630f6fa54560e41b815260040160405180910390fd5b6001600160a01b0385166132e05760405163538ba4f960e01b815260040160405180910390fd5b6001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1461331d576133186001600160a01b0384168684613033565b61335f565b8181101561333e5760405163e4f2466360e01b815260040160405180910390fd5b4781111561335f57604051632858f9ab60e11b815260040160405180910390fd5b6000856001600160a01b0316828660405161337a919061430f565b60006040518083038185875af1925050503d80600081146133b7576040519150601f19603f3d011682016040523d82523d6000602084013e6133bc565b606091505b50509050806133ee57604051632accaa1560e01b81526001600160a01b03851660048201526024015b60405180910390fd5b6001600160a01b03841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146134a457604051636eb1769f60e11b81523060048201526001600160a01b038781166024830152859160009183169063dd62ed3e90604401602060405180830381865afa158015613463573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134879190613e7c565b11156134a2576134a26001600160a01b03821688600061374e565b505b505050505050565b60a083015151516000908190156134c357306134ca565b8461010001515b6040516370a0823160e01b81526001600160a01b0380831660048301529192506000918516906370a0823190602401602060405180830381865afa158015613516573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353a9190613e7c565b6040878101519051635d043b2960e11b815260048101919091526001600160a01b0384811660248301523060448301529192509086169063ba087652906064016020604051808303816000875af1158015613599573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135bd9190613e7c565b6040516370a0823160e01b81526001600160a01b0384811660048301529194506000918616906370a0823190602401602060405180830381865afa158015613609573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061362d9190613e7c565b90508361363a83836142d2565b14158061367057506080870151613653906127106142d2565b876060015161366291906142e5565b61366e856127106142e5565b105b1561368e57604051635ebf8da160e11b815260040160405180910390fd5b8360000361328e5760405163affdc82f60e01b815260040160405180910390fd5b6000828411806136de57506136c6826127106142d2565b6136d090846142e5565b6136dc612710866142e5565b105b156118ff575060016118ff565b60006137006001600160a01b038416836137de565b90508051600014158015613725575080806020019051810190613723919061409f565b155b15612ff557604051635274afe760e01b81526001600160a01b03841660048201526024016133e5565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261379f84826137ec565b611d4c576040516001600160a01b038481166024830152600060448301526137d491869182169063095ea7b390606401612fc3565b611d4c84826136eb565b60606118ff8383600061388f565b6000806000846001600160a01b031684604051613809919061430f565b6000604051808303816000865af19150503d8060008114613846576040519150601f19603f3d011682016040523d82523d6000602084013e61384b565b606091505b5091509150818015613875575080511580613875575080806020019051810190613875919061409f565b80156112115750505050506001600160a01b03163b151590565b6060814710156138b45760405163cd78605960e01b81523060048201526024016133e5565b600080856001600160a01b031684866040516138d0919061430f565b60006040518083038185875af1925050503d806000811461390d576040519150601f19603f3d011682016040523d82523d6000602084013e613912565b606091505b509150915061392286838361392c565b9695505050505050565b6060826139415761393c82613988565b6118ff565b815115801561395857506001600160a01b0384163b155b1561398157604051639996b31560e01b81526001600160a01b03851660048201526024016133e5565b50806118ff565b8051156139985780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6000602082840312156139c357600080fd5b81356001600160e01b0319811681146118ff57600080fd5b6000602082840312156139ed57600080fd5b5035919050565b60005b83811015613a0f5781810151838201526020016139f7565b50506000910152565b60008151808452613a308160208601602086016139f4565b601f01601f19169290920160200192915050565b6020815260006118ff6020830184613a18565b6001600160a01b03811681146108f457600080fd5b8035613a7781613a57565b919050565b600060208284031215613a8e57600080fd5b81356118ff81613a57565b60008060408385031215613aac57600080fd5b8235613ab781613a57565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b60405161014081016001600160401b0381118282101715613afe57613afe613ac5565b60405290565b604051601f8201601f191681016001600160401b0381118282101715613b2c57613b2c613ac5565b604052919050565b60006001600160401b03821115613b4d57613b4d613ac5565b50601f01601f191660200190565b600082601f830112613b6c57600080fd5b8135613b7f613b7a82613b34565b613b04565b818152846020838601011115613b9457600080fd5b816020850160208301376000918101602001919091529392505050565b60ff811681146108f457600080fd5b80356001600160401b0381168114613a7757600080fd5b600060c08284031215613be957600080fd5b60405160c081016001600160401b038282108183111715613c0c57613c0c613ac5565b816040528293508435915080821115613c2457600080fd5b50613c3185828601613b5b565b8252506020830135613c4281613a57565b60208201526040830135613c5581613a57565b60408201526060830135613c6881613bb1565b6060820152613c7960808401613bc0565b608082015260a083013560a08201525092915050565b80151581146108f457600080fd5b8035613a7781613c8f565b60006101408284031215613cbb57600080fd5b613cc3613adb565b9050813581526020820135602082015260408201356040820152606082013560608201526080820135608082015260a08201356001600160401b0380821115613d0b57600080fd5b613d1785838601613bd7565b60a0840152613d2860c08501613c9d565b60c0840152613d3960e08501613c9d565b60e08401526101009150613d4e828501613a6c565b8284015261012091508184013581811115613d6857600080fd5b613d7486828701613b5b565b8385015250505092915050565b600080600060608486031215613d9657600080fd5b83356001600160401b03811115613dac57600080fd5b613db886828701613ca8565b9350506020840135613dc981613a57565b9150613dd760408501613bc0565b90509250925092565b60008060408385031215613df357600080fd5b82356001600160401b03811115613e0957600080fd5b613e1585828601613ca8565b9250506020830135613e2681613a57565b809150509250929050565b600080600060608486031215613e4657600080fd5b8335613e5181613a57565b92506020840135613e6181613a57565b91506040840135613e7181613a57565b809150509250925092565b600060208284031215613e8e57600080fd5b5051919050565b600060208284031215613ea757600080fd5b81516001600160401b03811115613ebd57600080fd5b8201601f81018413613ece57600080fd5b8051613edc613b7a82613b34565b818152856020838501011115613ef157600080fd5b6112118260208301602086016139f4565b6273702d60e81b815260008251613f208160038501602087016139f4565b9190910160030192915050565b60008251613f3f8184602087016139f4565b6d1029bab832b92837b9b4ba34b7b760911b920191825250600e01919050565b600060208284031215613f7157600080fd5b81516118ff81613bb1565b634e487b7160e01b600052601160045260246000fd5b600181815b80851115613fcd578160001904821115613fb357613fb3613f7c565b80851615613fc057918102915b93841c9390800290613f97565b509250929050565b600082613fe457506001610596565b81613ff157506000610596565b816001811461400757600281146140115761402d565b6001915050610596565b60ff84111561402257614022613f7c565b50506001821b610596565b5060208310610133831016604e8410600b8410161715614050575081810a610596565b61405a8383613f92565b806000190482111561406e5761406e613f7c565b029392505050565b60006118ff8383613fd5565b60006020828403121561409457600080fd5b81516118ff81613a57565b6000602082840312156140b157600080fd5b81516118ff81613c8f565b6000815160c084526140d160c0850182613a18565b9050602083015160018060a01b038082166020870152806040860151166040870152505060ff60608401511660608501526001600160401b03608084015116608085015260a083015160a08501528091505092915050565b6020815281516020820152602082015160408201526040820151606082015260608201516080820152608082015160a0820152600060a08301516101408060c085015261417a6101608501836140bc565b915060c085015161418f60e086018215159052565b5060e08501516101006141a58187018315159052565b86015190506101206141c1868201836001600160a01b03169052565b860151858403601f19018387015290506139228382613a18565b6040815260006141ee6040830185613a18565b905082151560208301529392505050565b602081526000825161012080602085015261421e610140850183613a18565b9150602085015161423a60408601826001600160401b03169052565b5060408501516001600160401b03811660608601525060608501516001600160401b038116608086015250608085015180151560a08601525060a08501516001600160a01b03811660c08601525060c08501516001600160a01b03811660e08601525060e08501516101006142b9818701836001600160a01b03169052565b909501516001600160a01b031693019290925250919050565b8181038181111561059657610596613f7c565b808202811582820484141761059657610596613f7c565b8082018082111561059657610596613f7c565b600082516143218184602087016139f4565b919091019291505056febcc180fb907e9ae431665de4bc74305c00b7b27442aadd477980ecc4bb14c011a26469706673582212200df59e65970b93b00d3113e859b9be5fafbc8485500f9eb2f1750a64a2579cfb64736f6c63430008170033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
Multichain Portfolio | 35 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.