Source Code (Proxy)
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 1,127 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Approve | 24071916 | 18 hrs ago | IN | 0 ETH | 0.00000124 | ||||
| Report | 24071033 | 21 hrs ago | IN | 0 ETH | 0.00005486 | ||||
| Approve | 24069516 | 26 hrs ago | IN | 0 ETH | 0.00000153 | ||||
| Report | 24063734 | 46 hrs ago | IN | 0 ETH | 0.00005226 | ||||
| Approve | 24063012 | 2 days ago | IN | 0 ETH | 0.0000014 | ||||
| Approve | 24063008 | 2 days ago | IN | 0 ETH | 0.00000666 | ||||
| Approve | 24063004 | 2 days ago | IN | 0 ETH | 0.00000403 | ||||
| Approve | 24062160 | 2 days ago | IN | 0 ETH | 0.00000168 | ||||
| Approve | 24058308 | 2 days ago | IN | 0 ETH | 0.00000128 | ||||
| Report | 24056404 | 2 days ago | IN | 0 ETH | 0.0000512 | ||||
| Report | 24049076 | 3 days ago | IN | 0 ETH | 0.00005361 | ||||
| Approve | 24043771 | 4 days ago | IN | 0 ETH | 0.00010025 | ||||
| Approve | 24043750 | 4 days ago | IN | 0 ETH | 0.0000015 | ||||
| Report | 24041781 | 4 days ago | IN | 0 ETH | 0.00027945 | ||||
| Approve | 24040481 | 5 days ago | IN | 0 ETH | 0.00003143 | ||||
| Approve | 24039892 | 5 days ago | IN | 0 ETH | 0.00002555 | ||||
| Approve | 24039886 | 5 days ago | IN | 0 ETH | 0.00003538 | ||||
| Report | 24034473 | 6 days ago | IN | 0 ETH | 0.0001432 | ||||
| Approve | 24031856 | 6 days ago | IN | 0 ETH | 0.00000106 | ||||
| Approve | 24031847 | 6 days ago | IN | 0 ETH | 0.0000016 | ||||
| Approve | 24029327 | 6 days ago | IN | 0 ETH | 0.00000634 | ||||
| Approve | 24029326 | 6 days ago | IN | 0 ETH | 0.0000064 | ||||
| Report | 24027173 | 7 days ago | IN | 0 ETH | 0.0000847 | ||||
| Report | 24019859 | 8 days ago | IN | 0 ETH | 0.00041575 | ||||
| Report | 24012538 | 9 days ago | IN | 0 ETH | 0.00009776 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
SuperVault
Compiler Version
v0.8.24+commit.e11b9ed9
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2024-12-09
*/
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.18 ^0.8.0 ^0.8.1 ^0.8.20 ^0.8.23 ^0.8.24;
// lib/superform-core/lib/ERC1155A/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
/**
* @dev Standard ERC-20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
*/
interface IERC20Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/
error ERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC-721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/
error ERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/
error ERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/
error ERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC-1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
*/
interface IERC1155Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/
error ERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}
// lib/superform-core/lib/ERC1155A/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
/**
* @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);
}
// lib/superform-core/lib/ERC1155A/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)
/**
* @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);
}
// lib/superform-core/lib/ERC1155A/lib/openzeppelin-contracts/contracts/utils/Address.sol
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)
/**
* @dev Collection of functions related to the address type
*/
library Address_0 {
/**
* @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();
}
}
}
// lib/superform-core/lib/ERC1155A/lib/openzeppelin-contracts/contracts/utils/Context.sol
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol)
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
// lib/superform-core/lib/ERC1155A/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
/**
* @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_0 {
/**
* @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);
}
// lib/superform-core/src/interfaces/IBaseSuperformRouterPlus.sol
interface IBaseSuperformRouterPlus {
//////////////////////////////////////////////////////////////
// ERRORS //
//////////////////////////////////////////////////////////////
/// @notice thrown if the provided selector is invalid
error INVALID_REBALANCE_SELECTOR();
//////////////////////////////////////////////////////////////
// STRUCTS //
//////////////////////////////////////////////////////////////
struct XChainRebalanceData {
bytes4 rebalanceSelector;
address interimAsset;
uint256 slippage;
uint256 expectedAmountInterimAsset;
uint8[][] rebalanceToAmbIds;
uint64[] rebalanceToDstChainIds;
bytes rebalanceToSfData;
}
//////////////////////////////////////////////////////////////
// ENUMS //
//////////////////////////////////////////////////////////////
enum Actions {
DEPOSIT,
REBALANCE_FROM_SINGLE,
REBALANCE_FROM_MULTI,
REBALANCE_X_CHAIN_FROM_SINGLE,
REBALANCE_X_CHAIN_FROM_MULTI
}
}
// lib/superform-core/src/interfaces/ISuperRegistry.sol
/// @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;
}
// lib/superform-core/src/interfaces/ISuperformFactory.sol
/// @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;
}
// lib/superform-core/src/libraries/Error.sol
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();
}
// lib/superform-core/src/types/DataTypes.sol
/// @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;
}
// lib/tokenized-strategy/lib/openzeppelin-contracts/contracts/utils/Address.sol
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
/**
* @dev Collection of functions related to the address type
*/
library Address_1 {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
// lib/tokenized-strategy/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165_1 {
/**
* @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[EIP 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);
}
// lib/tokenized-strategy/lib/openzeppelin-contracts/contracts/utils/math/Math.sol
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}
// lib/tokenized-strategy/lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol
// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```solidity
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}
// src/interfaces/ISuperformFactoryMinimal.sol
/// @title ISuperformFactoryMinimal Interface
/// @notice Minimal interface for the SuperformFactory contract
/// @author SuperForm Labs
interface ISuperformFactoryMinimal {
function vaultFormImplCombinationToSuperforms(bytes32 vaultFormImplementationCombination)
external
view
returns (uint256 superformId);
function getFormImplementation(uint32 formImplementationId_) external view returns (address);
}
// lib/superform-core/lib/ERC1155A/lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
// lib/superform-core/lib/ERC1155A/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/IERC1155.sol)
/**
* @dev Required interface of an ERC-1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[ERC].
*/
interface IERC1155 is IERC165_0 {
/**
* @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.
*/
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
/**
* @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
* transfers.
*/
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
/**
* @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
* `approved`.
*/
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
/**
* @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
*
* If an {URI} event was emitted for `id`, the standard
* https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
* returned by {IERC1155MetadataURI-uri}.
*/
event URI(string value, uint256 indexed id);
/**
* @dev Returns the value of tokens of token type `id` owned by `account`.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) external view returns (uint256);
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(
address[] calldata accounts,
uint256[] calldata ids
) external view returns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the caller.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address account, address operator) external view returns (bool);
/**
* @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.
*
* WARNING: This function can potentially allow a reentrancy attack when transferring tokens
* to an untrusted contract, when invoking {onERC1155Received} on the receiver.
* Ensure to follow the checks-effects-interactions pattern and consider employing
* reentrancy guards when interacting with untrusted contracts.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
* - `from` must have a balance of tokens of type `id` of at least `value` amount.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* WARNING: This function can potentially allow a reentrancy attack when transferring tokens
* to an untrusted contract, when invoking {onERC1155BatchReceived} on the receiver.
* Ensure to follow the checks-effects-interactions pattern and consider employing
* reentrancy guards when interacting with untrusted contracts.
*
* Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.
*
* Requirements:
*
* - `ids` and `values` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external;
}
// lib/superform-core/lib/ERC1155A/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/IERC1155Receiver.sol)
/**
* @dev Interface that must be implemented by smart contracts in order to receive
* ERC-1155 token transfers.
*/
interface IERC1155Receiver is IERC165_0 {
/**
* @dev Handles the receipt of a single ERC-1155 token type. This function is
* called at the end of a `safeTransferFrom` after the balance has been updated.
*
* NOTE: To accept the transfer, this must return
* `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
* (i.e. 0xf23a6e61, or its own function selector).
*
* @param operator The address which initiated the transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param id The ID of the token being transferred
* @param value The amount of tokens being transferred
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
*/
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
/**
* @dev Handles the receipt of a multiple ERC-1155 token types. This function
* is called at the end of a `safeBatchTransferFrom` after the balances have
* been updated.
*
* NOTE: To accept the transfer(s), this must return
* `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
* (i.e. 0xbc197c81, or its own function selector).
*
* @param operator The address which initiated the batch transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param ids An array containing ids of each token being transferred (order and length must match values array)
* @param values An array containing amounts of each token being transferred (order and length must match ids array)
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
*/
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}
// lib/superform-core/lib/ERC1155A/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.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);
}
// lib/superform-core/src/interfaces/IBaseRouter.sol
/// @title IBaseRouter
/// @dev Interface for abstract BaseRouter
/// @author Zeropoint Labs
interface IBaseRouter {
//////////////////////////////////////////////////////////////
// EXTERNAL WRITE FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @dev Performs single direct x single vault deposits
/// @param req_ is the request object containing all the necessary data for the action
function singleDirectSingleVaultDeposit(SingleDirectSingleVaultStateReq memory req_) external payable;
/// @dev Performs single xchain destination x single vault deposits
/// @param req_ is the request object containing all the necessary data for the action
function singleXChainSingleVaultDeposit(SingleXChainSingleVaultStateReq memory req_) external payable;
/// @dev Performs single direct x multi vault deposits
/// @param req_ is the request object containing all the necessary data for the action
function singleDirectMultiVaultDeposit(SingleDirectMultiVaultStateReq memory req_) external payable;
/// @dev Performs single destination x multi vault deposits
/// @param req_ is the request object containing all the necessary data for the action
function singleXChainMultiVaultDeposit(SingleXChainMultiVaultStateReq memory req_) external payable;
/// @dev Performs multi destination x single vault deposits
/// @param req_ is the request object containing all the necessary data for the action
function multiDstSingleVaultDeposit(MultiDstSingleVaultStateReq calldata req_) external payable;
/// @dev Performs multi destination x multi vault deposits
/// @param req_ is the request object containing all the necessary data for the action
function multiDstMultiVaultDeposit(MultiDstMultiVaultStateReq calldata req_) external payable;
/// @dev Performs single direct x single vault withdraws
/// @param req_ is the request object containing all the necessary data for the action
function singleDirectSingleVaultWithdraw(SingleDirectSingleVaultStateReq memory req_) external payable;
/// @dev Performs single xchain destination x single vault withdraws
/// @param req_ is the request object containing all the necessary data for the action
function singleXChainSingleVaultWithdraw(SingleXChainSingleVaultStateReq memory req_) external payable;
/// @dev Performs single direct x multi vault withdraws
/// @param req_ is the request object containing all the necessary data for the action
function singleDirectMultiVaultWithdraw(SingleDirectMultiVaultStateReq memory req_) external payable;
/// @dev Performs single destination x multi vault withdraws
/// @param req_ is the request object containing all the necessary data for the action
function singleXChainMultiVaultWithdraw(SingleXChainMultiVaultStateReq memory req_) external payable;
/// @dev Performs multi destination x single vault withdraws
/// @param req_ is the request object containing all the necessary data for the action
function multiDstSingleVaultWithdraw(MultiDstSingleVaultStateReq calldata req_) external payable;
/// @dev Performs multi destination x multi vault withdraws
/// @param req_ is the request object containing all the necessary data for the action
function multiDstMultiVaultWithdraw(MultiDstMultiVaultStateReq calldata req_) external payable;
/// @dev Forwards dust to Paymaster
/// @param token_ the token to forward
function forwardDustToPaymaster(address token_) external;
}
// lib/superform-core/src/libraries/DataLib.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;
}
}
// lib/superform-core/lib/ERC1155A/lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC4626.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);
}
// lib/superform-core/lib/ERC1155A/src/interfaces/IERC1155A.sol
/// @title IERC1155A
/// @author Zeropoint Labs
/// @dev Single/range based id approve capability with conversion to ERC20s
interface IERC1155A is IERC1155 {
//////////////////////////////////////////////////////////////
// EVENTS //
//////////////////////////////////////////////////////////////
/// @dev emitted when single id approval is set
event ApprovalForOne(address indexed owner, address indexed spender, uint256 id, uint256 amount);
/// @dev emitted when an ERC1155A id is transmuted to an aERC20
event TransmutedToERC20(address indexed user, uint256 id, uint256 amount, address indexed receiver);
/// @dev emitted when an aERC20 is transmuted to an ERC1155 id
event TransmutedToERC1155A(address indexed user, uint256 id, uint256 amount, address indexed receiver);
/// @dev emitted when multiple ERC1155A ids are transmuted to aERC20s
event TransmutedBatchToERC20(address indexed user, uint256[] ids, uint256[] amounts, address indexed receiver);
/// @dev emitted when multiple aERC20s are transmuted to ERC1155A ids
event TransmutedBatchToERC1155A(address indexed user, uint256[] ids, uint256[] amounts, address indexed receiver);
//////////////////////////////////////////////////////////////
// ERRORS //
//////////////////////////////////////////////////////////////
/// @dev thrown if aERC20 was already registered
error AERC20_ALREADY_REGISTERED();
/// @dev thrown if aERC20 was not registered
error AERC20_NOT_REGISTERED();
/// @dev thrown if allowance amount will be decreased below zero
error DECREASED_ALLOWANCE_BELOW_ZERO();
/// @dev thrown if the associated ERC1155A id has not been minted before registering an aERC20
error ID_NOT_MINTED_YET();
/// @dev thrown if there is a length mismatch in batch operations
error LENGTH_MISMATCH();
/// @dev thrown if transfer is made to address 0
error TRANSFER_TO_ADDRESS_ZERO();
/// @dev thrown if address is 0
error ZERO_ADDRESS();
//////////////////////////////////////////////////////////////
// EXTERNAL VIEW FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @notice Public getter for existing single id total supply
/// @param id id of the ERC1155
function totalSupply(uint256 id) external view returns (uint256);
/// @notice Public getter to know if a token id exists
/// @dev determines based on total supply for the id
/// @param id id of the ERC1155
function exists(uint256 id) external view returns (bool);
/// @notice Public getter for existing single id approval
/// @param owner address of the owner of the ERC1155A id
/// @param spender address of the contract to approve
/// @param id id of the ERC1155A to approve
function allowance(address owner, address spender, uint256 id) external returns (uint256);
/// @notice handy helper to check if a AERC20 is registered
/// @param id id of the ERC1155
function aERC20Exists(uint256 id) external view returns (bool);
/// @notice Public getter for the address of the aErc20 token for a given ERC1155 id
/// @param id id of the ERC1155 to get the aErc20 token address for
/// @return aERC20 address of the aErc20 token for the given ERC1155 id
function getERC20TokenAddress(uint256 id) external view returns (address aERC20);
/// @notice Compute return string from baseURI set for this contract and unique vaultId
/// @param id id of the ERC1155
function uri(uint256 id) external view returns (string memory);
/// @notice ERC1155A name
function name() external view returns (string memory);
/// @notice ERC1155A symbol
function symbol() external view returns (string memory);
//////////////////////////////////////////////////////////////
// EXTERNAL WRITE FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @notice Public function for setting single id approval
/// @dev Notice `owner` param, it will always be msg.sender, see _setApprovalForOne()
/// @param spender address of the contract to approve
/// @param id id of the ERC1155A to approve
/// @param amount amount of the ERC1155A to approve
function setApprovalForOne(address spender, uint256 id, uint256 amount) external;
/// @notice Public function for setting multiple id approval
/// @dev extension of sigle id approval
/// @param spender address of the contract to approve
/// @param ids ids of the ERC1155A to approve
/// @param amounts amounts of the ERC1155A to approve
function setApprovalForMany(address spender, uint256[] memory ids, uint256[] memory amounts) external;
/// @notice Public function for increasing single id approval amount
/// @dev Re-adapted from ERC20
/// @param spender address of the contract to approve
/// @param id id of the ERC1155A to approve
/// @param addedValue amount of the allowance to increase by
function increaseAllowance(address spender, uint256 id, uint256 addedValue) external returns (bool);
/// @notice Public function for decreasing single id approval amount
/// @dev Re-adapted from ERC20
/// @param spender address of the contract to approve
/// @param id id of the ERC1155A to approve
/// @param subtractedValue amount of the allowance to decrease by
function decreaseAllowance(address spender, uint256 id, uint256 subtractedValue) external returns (bool);
/// @notice Public function for increasing multiple id approval amount at once
/// @dev extension of single id increase allowance
/// @param spender address of the contract to approve
/// @param ids ids of the ERC1155A to approve
/// @param addedValues amounts of the allowance to increase by
function increaseAllowanceForMany(
address spender,
uint256[] memory ids,
uint256[] memory addedValues
)
external
returns (bool);
/// @notice Public function for decreasing multiple id approval amount at once
/// @dev extension of single id decrease allowance
/// @param spender address of the contract to approve
/// @param ids ids of the ERC1155A to approve
/// @param subtractedValues amounts of the allowance to decrease by
function decreaseAllowanceForMany(
address spender,
uint256[] memory ids,
uint256[] memory subtractedValues
)
external
returns (bool);
/// @notice Turn ERC1155A id into an aERC20
/// @dev allows owner to send ERC1155A id as an aERC20 to receiver
/// @param owner address of the user on whose behalf this transmutation is happening
/// @param id id of the ERC20s to transmute to aERC20
/// @param amount amount of the ERC20s to transmute to aERC20
/// @param receiver address of the user to receive the aERC20 token
function transmuteToERC20(address owner, uint256 id, uint256 amount, address receiver) external;
/// @notice Turn aERC20 into an ERC1155A id
/// @dev allows owner to send ERC20 as an ERC1155A id to receiver
/// @param owner address of the user on whose behalf this transmutation is happening
/// @param id id of the ERC20s to transmute to erc1155
/// @param amount amount of the ERC20s to transmute to erc1155
/// @param receiver address of the user to receive the erc1155 token id
function transmuteToERC1155A(address owner, uint256 id, uint256 amount, address receiver) external;
/// @notice Turn ERC1155A ids into aERC20s
/// @dev allows owner to send ERC1155A ids as aERC20s to receiver
/// @param owner address of the user on whose behalf this transmutation is happening
/// @param ids ids of the ERC1155A to transmute
/// @param amounts amounts of the ERC1155A to transmute
/// @param receiver address of the user to receive the aERC20 tokens
function transmuteBatchToERC20(
address owner,
uint256[] memory ids,
uint256[] memory amounts,
address receiver
)
external;
/// @notice Turn aERC20s into ERC1155A ids
/// @dev allows owner to send aERC20s as ERC1155A ids to receiver
/// @param owner address of the user on whose behalf this transmutation is happening
/// @param ids ids of the ERC20 to transmute
/// @param amounts amounts of the ERC20 to transmute
/// @param receiver address of the user to receive the ERC1155 token ids
function transmuteBatchToERC1155A(
address owner,
uint256[] memory ids,
uint256[] memory amounts,
address receiver
)
external;
/// @notice payable to allow any implementing cross-chain protocol to be paid for fees for broadcasting
/// @dev should emit any required events inside _registerAERC20 internal function
/// @param id of the ERC1155 to create a ERC20 for
function registerAERC20(uint256 id) external payable returns (address);
}
// src/interfaces/ISuperVault.sol
/// @title ISuperVault Interface
/// @notice Interface for the SuperVault contract
/// @author SuperForm Labs
interface ISuperVault is IERC1155Receiver {
//////////////////////////////////////////////////////////////
// STRUCTS //
//////////////////////////////////////////////////////////////
/// @notice Struct to hold rebalance arguments
/// @notice superformIdsRebalanceFrom must be an ordered array of superform IDs with no duplicates
/// @param superformIdsRebalanceFrom Array of superform IDs to rebalance from
/// @param amountsRebalanceFrom Array of amounts to rebalance from each superform
/// @param finalSuperformIds Array of final superform IDs
/// @param weightsOfRedestribution Array of weights for redistribution
/// @param slippage Slippage tolerance for the rebalance
struct RebalanceArgs {
uint256[] superformIdsRebalanceFrom;
uint256[] amountsRebalanceFrom;
uint256[] finalSuperformIds;
uint256[] weightsOfRedestribution;
uint256 slippage;
}
//////////////////////////////////////////////////////////////
// ERRORS //
//////////////////////////////////////////////////////////////
/// @notice Error thrown when no superforms are provided in constructor
error ZERO_SUPERFORMS();
/// @notice Error thrown when the ID is zero
error ZERO_ID();
/// @notice Error thrown when the address is zero
error ZERO_ADDRESS();
/// @notice Error thrown when duplicate superform IDs to rebalance from are provided
error DUPLICATE_SUPERFORM_IDS_REBALANCE_FROM();
/// @notice Error thrown when duplicate final superform IDs are provided
error DUPLICATE_FINAL_SUPERFORM_IDS();
/// @notice Error thrown when array lengths do not match
error ARRAY_LENGTH_MISMATCH();
/// @notice Error thrown when invalid weights are provided
error INVALID_WEIGHTS();
/// @notice Error thrown when the caller is not the Super Vaults strategist
error NOT_SUPER_VAULTS_STRATEGIST();
/// @notice Error thrown when the amounts to rebalance from array is empty
error EMPTY_AMOUNTS_REBALANCE_FROM();
/// @notice Error thrown when the final superform IDs array is empty
error EMPTY_FINAL_SUPERFORM_IDS();
/// @notice Error thrown when a superform does not support the asset
error SUPERFORM_DOES_NOT_SUPPORT_ASSET();
/// @notice Error thrown when the block chain ID is out of bounds
error BLOCK_CHAIN_ID_OUT_OF_BOUNDS();
/// @notice Error thrown when a superform does not exist
error SUPERFORM_DOES_NOT_EXIST(uint256 superformId);
/// @notice Error thrown when a superform ID is invalid
error INVALID_SUPERFORM_ID_REBALANCE_FROM();
/// @notice Error thrown when a superform ID is not found in the final superform IDs
error REBALANCE_FROM_ID_NOT_FOUND_IN_FINAL_IDS();
/// @notice Error thrown when the caller is not the pending management
error NOT_PENDING_MANAGEMENT();
/// @notice Error thrown when the caller is not the vault manager
error NOT_VAULT_MANAGER();
/// @notice Error thrown when a superform ID is not whitelisted
error SUPERFORM_NOT_WHITELISTED();
/// @notice Error thrown when a superform is fully rebalanced
error INVALID_SP_FULL_REBALANCE(uint256 superformId);
//////////////////////////////////////////////////////////////
// EVENTS //
//////////////////////////////////////////////////////////////
/// @notice Emitted when the SuperVault is rebalanced
/// @param finalSuperformIds Array of final superform IDs of the SuperVault
/// @param finalWeights Array of final weights of the SuperVault
event RebalanceComplete(uint256[] finalSuperformIds, uint256[] finalWeights);
/// @notice Emitted when the deposit limit is set
/// @param depositLimit The new deposit limit
event DepositLimitSet(uint256 depositLimit);
/// @notice Emitted when dust is forwarded to the paymaster
/// @param dust The amount of dust forwarded
event DustForwardedToPaymaster(uint256 dust);
/// @notice Emitted when the strategist is set
/// @param strategist The new strategist
event StrategistSet(address strategist);
/// @notice Emitted when a superform is whitelisted
/// @param superformId The superform ID that was whitelisted
/// @param isWhitelisted Whether the superform was whitelisted
event SuperformWhitelisted(uint256 superformId, bool isWhitelisted);
/// @notice Emitted when the vault manager is set
/// @param vaultManager The new vault manager
event VaultManagerSet(address vaultManager);
//////////////////////////////////////////////////////////////
// EXTERNAL FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @notice Sets the deposit limit for the vault
/// @param depositLimit_ The new deposit limit
function setDepositLimit(uint256 depositLimit_) external;
/// @notice Sets the strategist for the vault
/// @param strategist_ The new strategist
function setStrategist(address strategist_) external;
/// @notice Sets the valid 5115 form implementation ID for the vault
/// @param formImplementationId_ The form implementation ID
function setValid5115FormImplementationId(uint32 formImplementationId_) external;
/// @notice Rebalances the SuperVault
/// @notice rebalanceArgs_.superformIdsRebalanceFrom must be an ordered array of superform IDs with no duplicates
/// @notice the logic is as follows:
/// select the ids to rebalance from
/// send an amount to take from those ids
/// the total underlying asset amount is redestributed according to the desired weights
function rebalance(RebalanceArgs memory rebalanceArgs_) external payable;
/// @notice Forwards dust to the paymaster
function forwardDustToPaymaster() external;
/// @notice Sets the whitelist for Superform IDs
/// @param superformIds Array of Superform IDs
/// @param isWhitelisted Array of booleans indicating whether to whitelist or blacklist
function setWhitelist(uint256[] memory superformIds, bool[] memory isWhitelisted) external;
/// @notice Sets the vault manager
/// @param vaultManager_ The new vault manager
function setVaultManager(address vaultManager_) external;
/// @notice Returns whether a Superform ID is whitelisted
/// @param superformIds Array of Superform IDs
/// @return isWhitelisted Array of booleans indicating whether each Superform ID is whitelisted
function getIsWhitelisted(uint256[] memory superformIds) external view returns (bool[] memory isWhitelisted);
/// @notice Returns the array of whitelisted Superform IDs
/// @return Array of whitelisted Superform IDs
function getWhitelist() external view returns (uint256[] memory);
/// @notice Returns the superform IDs and weights of the SuperVault
/// @return superformIds_ Array of superform IDs
/// @return weights_ Array of weights
function getSuperVaultData() external view returns (uint256[] memory superformIds_, uint256[] memory weights_);
}
// lib/superform-core/lib/ERC1155A/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.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_0 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;
}
}
// lib/superform-core/src/interfaces/ISuperformRouterPlus.sol
interface ISuperformRouterPlus is IBaseSuperformRouterPlus {
//////////////////////////////////////////////////////////////
// ERRORS //
//////////////////////////////////////////////////////////////
/// @notice thrown when an invalid rebalance from selector is provided
error INVALID_REBALANCE_FROM_SELECTOR();
/// @notice thrown when an invalid deposit selector provided
error INVALID_DEPOSIT_SELECTOR();
/// @notice thrown if the interimToken is different than expected
error REBALANCE_SINGLE_POSITIONS_DIFFERENT_TOKEN();
/// @notice thrown if the liqDstChainId is different than expected
error REBALANCE_SINGLE_POSITIONS_DIFFERENT_CHAIN();
/// @notice thrown if the amounts to redeem differ
error REBALANCE_SINGLE_POSITIONS_DIFFERENT_AMOUNT();
/// @notice thrown if the receiver address is invalid (not the router plus)
error REBALANCE_SINGLE_POSITIONS_UNEXPECTED_RECEIVER_ADDRESS();
/// @notice thrown if the interimToken is different than expected in the array
error REBALANCE_MULTI_POSITIONS_DIFFERENT_TOKEN();
/// @notice thrown if the liqDstChainId is different than expected in the array
error REBALANCE_MULTI_POSITIONS_DIFFERENT_CHAIN();
/// @notice thrown if the amounts to redeem differ
error REBALANCE_MULTI_POSITIONS_DIFFERENT_AMOUNTS();
/// @notice thrown if the receiver address is invalid (not the router plus)
error REBALANCE_MULTI_POSITIONS_UNEXPECTED_RECEIVER_ADDRESS();
/// @notice thrown if the receiver address is invalid (not the router plus)
error REBALANCE_XCHAIN_INVALID_RECEIVER_ADDRESS();
/// @notice thrown if msg.value is lower than the required fee
error INVALID_FEE();
/// @notice thrown if the amount of assets received is lower than the slippage
error ASSETS_RECEIVED_OUT_OF_SLIPPAGE();
/// @notice thrown if the slippage is invalid
error INVALID_GLOBAL_SLIPPAGE();
/// @notice thrown if the tolerance is exceeded during shares redemption
error TOLERANCE_EXCEEDED();
/// @notice thrown if the amountIn is not equal or lower than the balance available
error AMOUNT_IN_NOT_EQUAL_OR_LOWER_THAN_BALANCE();
//////////////////////////////////////////////////////////////
// EVENTS //
//////////////////////////////////////////////////////////////
/// @notice emitted when a single position rebalance is completed
/// @param receiver The address receiving the rebalanced position
/// @param id The ID of the rebalanced position
/// @param amount The amount of tokens rebalanced
event RebalanceSyncCompleted(address indexed receiver, uint256 indexed id, uint256 amount);
/// @notice emitted when multiple positions are rebalanced
/// @param receiver The address receiving the rebalanced positions
/// @param ids The IDs of the rebalanced positions
/// @param amounts The amounts of tokens rebalanced for each position
event RebalanceMultiSyncCompleted(address indexed receiver, uint256[] ids, uint256[] amounts);
/// @notice emitted when a cross-chain rebalance is initiated
/// @param receiver The address receiving the rebalanced position
/// @param routerPlusPayloadId The router plus payload Id
/// @param id The ID of the position being rebalanced
/// @param amount The amount of tokens being rebalanced
/// @param interimAsset The address of the interim asset used in the cross-chain transfer
/// @param finalizeSlippage The slippage tolerance for the finalization step
/// @param expectedAmountInterimAsset The expected amount of interim asset to be received
/// @param rebalanceToSelector The selector for the rebalance to function
event XChainRebalanceInitiated(
address indexed receiver,
uint256 indexed routerPlusPayloadId,
uint256 id,
uint256 amount,
address interimAsset,
uint256 finalizeSlippage,
uint256 expectedAmountInterimAsset,
bytes4 rebalanceToSelector
);
/// @notice emitted when multiple cross-chain rebalances are initiated
/// @param receiver The address receiving the rebalanced positions
/// @param routerPlusPayloadId The router plus payload Id
/// @param ids The IDs of the positions being rebalanced
/// @param amounts The amounts of tokens being rebalanced for each position
/// @param interimAsset The address of the interim asset used in the cross-chain transfer
/// @param finalizeSlippage The slippage tolerance for the finalization step
/// @param expectedAmountInterimAsset The expected amount of interim asset to be received
/// @param rebalanceToSelector The selector for the rebalance to function
event XChainRebalanceMultiInitiated(
address indexed receiver,
uint256 indexed routerPlusPayloadId,
uint256[] ids,
uint256[] amounts,
address interimAsset,
uint256 finalizeSlippage,
uint256 expectedAmountInterimAsset,
bytes4 rebalanceToSelector
);
/// @notice emitted when a deposit from an ERC4626 vault is completed
/// @param receiver The address receiving the deposited tokens
/// @param vault The address of the ERC4626 vault
event Deposit4626Completed(address indexed receiver, address indexed vault);
/// @notice emitted when dust is forwarded to the paymaster
/// @param token The address of the token
/// @param amount The amount of tokens forwarded
event RouterPlusDustForwardedToPaymaster(address indexed token, uint256 amount);
//////////////////////////////////////////////////////////////
// STRUCTS //
//////////////////////////////////////////////////////////////
struct RebalanceSinglePositionSyncArgs {
uint256 id;
uint256 sharesToRedeem;
uint256 expectedAmountToReceivePostRebalanceFrom;
uint256 rebalanceFromMsgValue;
uint256 rebalanceToMsgValue;
address interimAsset;
uint256 slippage;
address receiverAddressSP;
bytes callData;
bytes rebalanceToCallData;
}
struct RebalanceMultiPositionsSyncArgs {
uint256[] ids;
uint256[] sharesToRedeem;
uint256 expectedAmountToReceivePostRebalanceFrom;
uint256 rebalanceFromMsgValue;
uint256 rebalanceToMsgValue;
address interimAsset;
uint256 slippage;
address receiverAddressSP;
bytes callData;
bytes rebalanceToCallData;
}
struct RebalancePositionsSyncArgs {
Actions action;
uint256[] sharesToRedeem;
uint256 expectedAmountToReceivePostRebalanceFrom;
address interimAsset;
uint256 slippage;
uint256 rebalanceFromMsgValue;
uint256 rebalanceToMsgValue;
address receiverAddressSP;
uint256 balanceBefore;
}
struct InitiateXChainRebalanceArgs {
uint256 id;
uint256 sharesToRedeem;
address receiverAddressSP;
address interimAsset;
uint256 finalizeSlippage;
uint256 expectedAmountInterimAsset;
bytes4 rebalanceToSelector;
bytes callData;
uint8[][] rebalanceToAmbIds;
uint64[] rebalanceToDstChainIds;
bytes rebalanceToSfData;
}
struct InitiateXChainRebalanceMultiArgs {
uint256[] ids;
uint256[] sharesToRedeem;
address receiverAddressSP;
address interimAsset;
uint256 finalizeSlippage;
uint256 expectedAmountInterimAsset;
bytes4 rebalanceToSelector;
bytes callData;
uint8[][] rebalanceToAmbIds;
uint64[] rebalanceToDstChainIds;
bytes rebalanceToSfData;
}
struct Deposit4626Args {
uint256 amount;
uint256 expectedOutputAmount;
uint256 maxSlippage;
address receiverAddressSP;
bytes depositCallData;
}
//////////////////////////////////////////////////////////////
// EXTERNAL WRITE FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @notice rebalances a single SuperPosition synchronously
/// @notice interim asset and receiverAddressSP must be set. In non smart contract wallet rebalances,
/// receiverAddressSP is only used for refunds
/// @param args The arguments for rebalancing single positions
function rebalanceSinglePosition(RebalanceSinglePositionSyncArgs calldata args) external payable;
/// @notice rebalances multiple SuperPositions synchronously
/// @notice interim asset and receiverAddressSP must be set. In non smart contract wallet rebalances,
/// receiverAddressSP is only used for refunds
/// @notice receiverAddressSP of rebalanceCallData must be the address of the router plus for smart wallets
/// @notice for normal deposits receiverAddressSP is the users' specified receiverAddressSP
/// @param args The arguments for rebalancing multiple positions
function rebalanceMultiPositions(RebalanceMultiPositionsSyncArgs calldata args) external payable;
/// @notice initiates the rebalance process for a position on a different chain
/// @param args The arguments for initiating cross-chain rebalance for single positions
function startCrossChainRebalance(InitiateXChainRebalanceArgs calldata args) external payable;
/// @notice initiates the rebalance process for multiple positions on different chains
/// @param args The arguments for initiating cross-chain rebalance for multiple positions
function startCrossChainRebalanceMulti(InitiateXChainRebalanceMultiArgs memory args) external payable;
/// @notice deposits ERC4626 vault shares into superform
/// @param vaults_ The ERC4626 vaults to redeem from
/// @param args Rest of the arguments to deposit 4626
function deposit4626(address[] calldata vaults_, Deposit4626Args[] calldata args) external payable;
/// @dev Forwards dust to Paymaster
/// @param token_ the token to forward
function forwardDustToPaymaster(address token_) external;
/// @dev only callable by Emergency Admin
/// @notice sets the global slippage for all rebalances
/// @param slippage_ The slippage tolerance for same chain rebalances
function setGlobalSlippage(uint256 slippage_) external;
}
// lib/superform-core/lib/ERC1155A/lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
*
* TIP: For a detailed writeup see our guide
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* The default value of {decimals} is 18. To change this, you should override
* this function so it returns a different value.
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC-20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the ERC may not emit
* these events, as it isn't required by the specification.
*/
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
mapping(address account => uint256) private _balances;
mapping(address account => mapping(address spender => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the default value returned by this function, unless
* it's overridden.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `value`.
*/
function transfer(address to, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_transfer(owner, to, value);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, value);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the ERC. See the note at the beginning of {ERC20}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `value`.
* - the caller must have allowance for ``from``'s tokens of at least
* `value`.
*/
function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, value);
_transfer(from, to, value);
return true;
}
/**
* @dev Moves a `value` amount of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _transfer(address from, address to, uint256 value) internal {
if (from == address(0)) {
revert ERC20InvalidSender(address(0));
}
if (to == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(from, to, value);
}
/**
* @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
* (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
* this function.
*
* Emits a {Transfer} event.
*/
function _update(address from, address to, uint256 value) internal virtual {
if (from == address(0)) {
// Overflow check required: The rest of the code assumes that totalSupply never overflows
_totalSupply += value;
} else {
uint256 fromBalance = _balances[from];
if (fromBalance < value) {
revert ERC20InsufficientBalance(from, fromBalance, value);
}
unchecked {
// Overflow not possible: value <= fromBalance <= totalSupply.
_balances[from] = fromBalance - value;
}
}
if (to == address(0)) {
unchecked {
// Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
_totalSupply -= value;
}
} else {
unchecked {
// Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
_balances[to] += value;
}
}
emit Transfer(from, to, value);
}
/**
* @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
* Relies on the `_update` mechanism
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _mint(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(address(0), account, value);
}
/**
* @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
* Relies on the `_update` mechanism.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead
*/
function _burn(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidSender(address(0));
}
_update(account, address(0), value);
}
/**
* @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
*/
function _approve(address owner, address spender, uint256 value) internal {
_approve(owner, spender, value, true);
}
/**
* @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
*
* By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
* `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
* `Approval` event during `transferFrom` operations.
*
* Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
* true using the following override:
* ```
* function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
* super._approve(owner, spender, value, true);
* }
* ```
*
* Requirements are the same as {_approve}.
*/
function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
if (owner == address(0)) {
revert ERC20InvalidApprover(address(0));
}
if (spender == address(0)) {
revert ERC20InvalidSpender(address(0));
}
_allowances[owner][spender] = value;
if (emitEvent) {
emit Approval(owner, spender, value);
}
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `value`.
*
* Does not update the allowance value in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Does not emit an {Approval} event.
*/
function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
if (currentAllowance < value) {
revert ERC20InsufficientAllowance(spender, currentAllowance, value);
}
unchecked {
_approve(owner, spender, currentAllowance - value, false);
}
}
}
}
// lib/superform-core/src/interfaces/ISuperPositions.sol
/// @title ISuperPositions
/// @dev Interface for SuperPositions
/// @author Zeropoint Labs
interface ISuperPositions is IERC1155A {
//////////////////////////////////////////////////////////////
// STRUCTS //
//////////////////////////////////////////////////////////////
struct TxHistory {
uint256 txInfo;
address receiverAddressSP;
}
//////////////////////////////////////////////////////////////
// EVENTS //
//////////////////////////////////////////////////////////////
/// @dev is emitted when a dynamic uri is updated
event DynamicURIUpdated(string indexed oldURI, string indexed newURI, bool indexed frozen);
/// @dev is emitted when a cross-chain transaction is completed.
event Completed(uint256 indexed txId);
/// @dev is emitted when a aErc20 token is registered
event AERC20TokenRegistered(uint256 indexed tokenId, address indexed tokenAddress);
/// @dev is emitted when a tx info is saved
event TxHistorySet(uint256 indexed payloadId, uint256 txInfo, address indexed receiverAddress);
//////////////////////////////////////////////////////////////
// EXTERNAL VIEW FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @dev returns the payload header and the receiver address for a tx id on the source chain
/// @param txId_ is the identifier of the transaction issued by superform router
/// @return txInfo is the header of the payload
/// @return receiverAddressSP is the address of the receiver of superPositions
function txHistory(uint256 txId_) external view returns (uint256 txInfo, address receiverAddressSP);
//////////////////////////////////////////////////////////////
// EXTERNAL WRITE FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @dev saves the message being sent together with the associated id formulated in a router
/// @param payloadId_ is the id of the message being saved
/// @param txInfo_ is the header of the AMBMessage of the transaction being saved
/// @param receiverAddressSP_ is the address of the receiver of superPositions
function updateTxHistory(uint256 payloadId_, uint256 txInfo_, address receiverAddressSP_) external;
/// @dev allows minter to mint shares on source
/// @param receiverAddress_ is the beneficiary of shares
/// @param id_ is the id of the shares
/// @param amount_ is the amount of shares to mint
function mintSingle(address receiverAddress_, uint256 id_, uint256 amount_) external;
/// @dev allows minter to mint shares on source in batch
/// @param receiverAddress_ is the beneficiary of shares
/// @param ids_ are the ids of the shares
/// @param amounts_ are the amounts of shares to mint
function mintBatch(address receiverAddress_, uint256[] memory ids_, uint256[] memory amounts_) external;
/// @dev allows superformRouter to burn shares on source
/// @notice burn is done optimistically by the router in the beginning of the withdraw transactions
/// @notice in case the withdraw tx fails on the destination, shares are reminted through stateSync
/// @param srcSender_ is the address of the sender
/// @param id_ is the id of the shares
/// @param amount_ is the amount of shares to burn
function burnSingle(address srcSender_, uint256 id_, uint256 amount_) external;
/// @dev allows burner to burn shares on source in batch
/// @param srcSender_ is the address of the sender
/// @param ids_ are the ids of the shares
/// @param amounts_ are the amounts of shares to burn
function burnBatch(address srcSender_, uint256[] memory ids_, uint256[] memory amounts_) external;
/// @dev allows state registry contract to mint shares on source
/// @param data_ is the received information to be processed.
/// @return srcChainId_ is the decoded srcChainId.
function stateMultiSync(AMBMessage memory data_) external returns (uint64 srcChainId_);
/// @dev allows state registry contract to mint shares on source
/// @param data_ is the received information to be processed.
/// @return srcChainId_ is the decoded srcChainId.
function stateSync(AMBMessage memory data_) external returns (uint64 srcChainId_);
/// @dev sets the dynamic uri for NFT
/// @param dynamicURI_ is the dynamic uri of the NFT
/// @param freeze_ is to prevent updating the metadata once migrated to IPFS
function setDynamicURI(string memory dynamicURI_, bool freeze_) external;
/// @dev allows to create sERC0 using broadcast state registry
/// @param data_ is the crosschain payload
function stateSyncBroadcast(bytes memory data_) external payable;
}
// lib/superform-core/src/interfaces/IBaseForm.sol
/// @title IBaseForm
/// @dev Interface for BaseForm
/// @author ZeroPoint Labs
interface IBaseForm is IERC165_0 {
//////////////////////////////////////////////////////////////
// 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;
}
// lib/tokenized-strategy/src/interfaces/ITokenizedStrategy.sol
// Interface that implements the 4626 standard and the implementation functions
interface ITokenizedStrategy is IERC4626, IERC20Permit {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event StrategyShutdown();
event NewTokenizedStrategy(
address indexed strategy,
address indexed asset,
string apiVersion
);
event Reported(
uint256 profit,
uint256 loss,
uint256 protocolFees,
uint256 performanceFees
);
event UpdatePerformanceFeeRecipient(
address indexed newPerformanceFeeRecipient
);
event UpdateKeeper(address indexed newKeeper);
event UpdatePerformanceFee(uint16 newPerformanceFee);
event UpdateManagement(address indexed newManagement);
event UpdateEmergencyAdmin(address indexed newEmergencyAdmin);
event UpdateProfitMaxUnlockTime(uint256 newProfitMaxUnlockTime);
event UpdatePendingManagement(address indexed newPendingManagement);
/*//////////////////////////////////////////////////////////////
INITIALIZATION
//////////////////////////////////////////////////////////////*/
function initialize(
address _asset,
string memory _name,
address _management,
address _performanceFeeRecipient,
address _keeper
) external;
/*//////////////////////////////////////////////////////////////
NON-STANDARD 4626 OPTIONS
//////////////////////////////////////////////////////////////*/
function withdraw(
uint256 assets,
address receiver,
address owner,
uint256 maxLoss
) external returns (uint256);
function redeem(
uint256 shares,
address receiver,
address owner,
uint256 maxLoss
) external returns (uint256);
/*//////////////////////////////////////////////////////////////
MODIFIER HELPERS
//////////////////////////////////////////////////////////////*/
function requireManagement(address _sender) external view;
function requireKeeperOrManagement(address _sender) external view;
function requireEmergencyAuthorized(address _sender) external view;
/*//////////////////////////////////////////////////////////////
KEEPERS FUNCTIONS
//////////////////////////////////////////////////////////////*/
function tend() external;
function report() external returns (uint256 _profit, uint256 _loss);
/*//////////////////////////////////////////////////////////////
CONSTANTS
//////////////////////////////////////////////////////////////*/
function MAX_FEE() external view returns (uint16);
function FACTORY() external view returns (address);
/*//////////////////////////////////////////////////////////////
GETTERS
//////////////////////////////////////////////////////////////*/
function apiVersion() external view returns (string memory);
function pricePerShare() external view returns (uint256);
function management() external view returns (address);
function pendingManagement() external view returns (address);
function keeper() external view returns (address);
function emergencyAdmin() external view returns (address);
function performanceFee() external view returns (uint16);
function performanceFeeRecipient() external view returns (address);
function fullProfitUnlockDate() external view returns (uint256);
function profitUnlockingRate() external view returns (uint256);
function profitMaxUnlockTime() external view returns (uint256);
function lastReport() external view returns (uint256);
function isShutdown() external view returns (bool);
function unlockedShares() external view returns (uint256);
/*//////////////////////////////////////////////////////////////
SETTERS
//////////////////////////////////////////////////////////////*/
function setPendingManagement(address) external;
function acceptManagement() external;
function setKeeper(address _keeper) external;
function setEmergencyAdmin(address _emergencyAdmin) external;
function setPerformanceFee(uint16 _performanceFee) external;
function setPerformanceFeeRecipient(
address _performanceFeeRecipient
) external;
function setProfitMaxUnlockTime(uint256 _profitMaxUnlockTime) external;
function shutdownStrategy() external;
function emergencyWithdraw(uint256 _amount) external;
}
// lib/tokenized-strategy/src/BaseStrategy.sol
// TokenizedStrategy interface used for internal view delegateCalls.
/**
* @title YearnV3 Base Strategy
* @author yearn.finance
* @notice
* BaseStrategy implements all of the required functionality to
* seamlessly integrate with the `TokenizedStrategy` implementation contract
* allowing anyone to easily build a fully permissionless ERC-4626 compliant
* Vault by inheriting this contract and overriding three simple functions.
* It utilizes an immutable proxy pattern that allows the BaseStrategy
* to remain simple and small. All standard logic is held within the
* `TokenizedStrategy` and is reused over any n strategies all using the
* `fallback` function to delegatecall the implementation so that strategists
* can only be concerned with writing their strategy specific code.
*
* This contract should be inherited and the three main abstract methods
* `_deployFunds`, `_freeFunds` and `_harvestAndReport` implemented to adapt
* the Strategy to the particular needs it has to generate yield. There are
* other optional methods that can be implemented to further customize
* the strategy if desired.
*
* All default storage for the strategy is controlled and updated by the
* `TokenizedStrategy`. The implementation holds a storage struct that
* contains all needed global variables in a manual storage slot. This
* means strategists can feel free to implement their own custom storage
* variables as they need with no concern of collisions. All global variables
* can be viewed within the Strategy by a simple call using the
* `TokenizedStrategy` variable. IE: TokenizedStrategy.globalVariable();.
*/
abstract contract BaseStrategy {
/*//////////////////////////////////////////////////////////////
MODIFIERS
//////////////////////////////////////////////////////////////*/
/**
* @dev Used on TokenizedStrategy callback functions to make sure it is post
* a delegateCall from this address to the TokenizedStrategy.
*/
modifier onlySelf() {
_onlySelf();
_;
}
/**
* @dev Use to assure that the call is coming from the strategies management.
*/
modifier onlyManagement() {
TokenizedStrategy.requireManagement(msg.sender);
_;
}
/**
* @dev Use to assure that the call is coming from either the strategies
* management or the keeper.
*/
modifier onlyKeepers() {
TokenizedStrategy.requireKeeperOrManagement(msg.sender);
_;
}
/**
* @dev Use to assure that the call is coming from either the strategies
* management or the emergency admin.
*/
modifier onlyEmergencyAuthorized() {
TokenizedStrategy.requireEmergencyAuthorized(msg.sender);
_;
}
/**
* @dev Require that the msg.sender is this address.
*/
function _onlySelf() internal view {
require(msg.sender == address(this), "!self");
}
/*//////////////////////////////////////////////////////////////
CONSTANTS
//////////////////////////////////////////////////////////////*/
/**
* @dev This is the address of the TokenizedStrategy implementation
* contract that will be used by all strategies to handle the
* accounting, logic, storage etc.
*
* Any external calls to the that don't hit one of the functions
* defined in this base or the strategy will end up being forwarded
* through the fallback function, which will delegateCall this address.
*
* This address should be the same for every strategy, never be adjusted
* and always be checked before any integration with the Strategy.
*/
address public constant tokenizedStrategyAddress =
0xBB51273D6c746910C7C06fe718f30c936170feD0;
/*//////////////////////////////////////////////////////////////
IMMUTABLES
//////////////////////////////////////////////////////////////*/
/**
* @dev Underlying asset the Strategy is earning yield on.
* Stored here for cheap retrievals within the strategy.
*/
ERC20 internal immutable asset;
/**
* @dev This variable is set to address(this) during initialization of each strategy.
*
* This can be used to retrieve storage data within the strategy
* contract as if it were a linked library.
*
* i.e. uint256 totalAssets = TokenizedStrategy.totalAssets()
*
* Using address(this) will mean any calls using this variable will lead
* to a call to itself. Which will hit the fallback function and
* delegateCall that to the actual TokenizedStrategy.
*/
ITokenizedStrategy internal immutable TokenizedStrategy;
/**
* @notice Used to initialize the strategy on deployment.
*
* This will set the `TokenizedStrategy` variable for easy
* internal view calls to the implementation. As well as
* initializing the default storage variables based on the
* parameters and using the deployer for the permissioned roles.
*
* @param _asset Address of the underlying asset.
* @param _name Name the strategy will use.
*/
constructor(address _asset, string memory _name) {
asset = ERC20(_asset);
// Set instance of the implementation for internal use.
TokenizedStrategy = ITokenizedStrategy(address(this));
// Initialize the strategy's storage variables.
_delegateCall(
abi.encodeCall(
ITokenizedStrategy.initialize,
(_asset, _name, msg.sender, msg.sender, msg.sender)
)
);
// Store the tokenizedStrategyAddress at the standard implementation
// address storage slot so etherscan picks up the interface. This gets
// stored on initialization and never updated.
assembly {
sstore(
// keccak256('eip1967.proxy.implementation' - 1)
0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc,
tokenizedStrategyAddress
)
}
}
/*//////////////////////////////////////////////////////////////
NEEDED TO BE OVERRIDDEN BY STRATEGIST
//////////////////////////////////////////////////////////////*/
/**
* @dev Can deploy up to '_amount' of 'asset' in the yield source.
*
* This function is called at the end of a {deposit} or {mint}
* call. Meaning that unless a whitelist is implemented it will
* be entirely permissionless and thus can be sandwiched or otherwise
* manipulated.
*
* @param _amount The amount of 'asset' that the strategy can attempt
* to deposit in the yield source.
*/
function _deployFunds(uint256 _amount) internal virtual;
/**
* @dev Should attempt to free the '_amount' of 'asset'.
*
* NOTE: The amount of 'asset' that is already loose has already
* been accounted for.
*
* This function is called during {withdraw} and {redeem} calls.
* Meaning that unless a whitelist is implemented it will be
* entirely permissionless and thus can be sandwiched or otherwise
* manipulated.
*
* Should not rely on asset.balanceOf(address(this)) calls other than
* for diff accounting purposes.
*
* Any difference between `_amount` and what is actually freed will be
* counted as a loss and passed on to the withdrawer. This means
* care should be taken in times of illiquidity. It may be better to revert
* if withdraws are simply illiquid so not to realize incorrect losses.
*
* @param _amount, The amount of 'asset' to be freed.
*/
function _freeFunds(uint256 _amount) internal virtual;
/**
* @dev Internal function to harvest all rewards, redeploy any idle
* funds and return an accurate accounting of all funds currently
* held by the Strategy.
*
* This should do any needed harvesting, rewards selling, accrual,
* redepositing etc. to get the most accurate view of current assets.
*
* NOTE: All applicable assets including loose assets should be
* accounted for in this function.
*
* Care should be taken when relying on oracles or swap values rather
* than actual amounts as all Strategy profit/loss accounting will
* be done based on this returned value.
*
* This can still be called post a shutdown, a strategist can check
* `TokenizedStrategy.isShutdown()` to decide if funds should be
* redeployed or simply realize any profits/losses.
*
* @return _totalAssets A trusted and accurate account for the total
* amount of 'asset' the strategy currently holds including idle funds.
*/
function _harvestAndReport()
internal
virtual
returns (uint256 _totalAssets);
/*//////////////////////////////////////////////////////////////
OPTIONAL TO OVERRIDE BY STRATEGIST
//////////////////////////////////////////////////////////////*/
/**
* @dev Optional function for strategist to override that can
* be called in between reports.
*
* If '_tend' is used tendTrigger() will also need to be overridden.
*
* This call can only be called by a permissioned role so may be
* through protected relays.
*
* This can be used to harvest and compound rewards, deposit idle funds,
* perform needed position maintenance or anything else that doesn't need
* a full report for.
*
* EX: A strategy that can not deposit funds without getting
* sandwiched can use the tend when a certain threshold
* of idle to totalAssets has been reached.
*
* This will have no effect on PPS of the strategy till report() is called.
*
* @param _totalIdle The current amount of idle funds that are available to deploy.
*/
function _tend(uint256 _totalIdle) internal virtual {}
/**
* @dev Optional trigger to override if tend() will be used by the strategy.
* This must be implemented if the strategy hopes to invoke _tend().
*
* @return . Should return true if tend() should be called by keeper or false if not.
*/
function _tendTrigger() internal view virtual returns (bool) {
return false;
}
/**
* @notice Returns if tend() should be called by a keeper.
*
* @return . Should return true if tend() should be called by keeper or false if not.
* @return . Calldata for the tend call.
*/
function tendTrigger() external view virtual returns (bool, bytes memory) {
return (
// Return the status of the tend trigger.
_tendTrigger(),
// And the needed calldata either way.
abi.encodeWithSelector(ITokenizedStrategy.tend.selector)
);
}
/**
* @notice Gets the max amount of `asset` that an address can deposit.
* @dev Defaults to an unlimited amount for any address. But can
* be overridden by strategists.
*
* This function will be called before any deposit or mints to enforce
* any limits desired by the strategist. This can be used for either a
* traditional deposit limit or for implementing a whitelist etc.
*
* EX:
* if(isAllowed[_owner]) return super.availableDepositLimit(_owner);
*
* This does not need to take into account any conversion rates
* from shares to assets. But should know that any non max uint256
* amounts may be converted to shares. So it is recommended to keep
* custom amounts low enough as not to cause overflow when multiplied
* by `totalSupply`.
*
* @param . The address that is depositing into the strategy.
* @return . The available amount the `_owner` can deposit in terms of `asset`
*/
function availableDepositLimit(
address /*_owner*/
) public view virtual returns (uint256) {
return type(uint256).max;
}
/**
* @notice Gets the max amount of `asset` that can be withdrawn.
* @dev Defaults to an unlimited amount for any address. But can
* be overridden by strategists.
*
* This function will be called before any withdraw or redeem to enforce
* any limits desired by the strategist. This can be used for illiquid
* or sandwichable strategies. It should never be lower than `totalIdle`.
*
* EX:
* return TokenIzedStrategy.totalIdle();
*
* This does not need to take into account the `_owner`'s share balance
* or conversion rates from shares to assets.
*
* @param . The address that is withdrawing from the strategy.
* @return . The available amount that can be withdrawn in terms of `asset`
*/
function availableWithdrawLimit(
address /*_owner*/
) public view virtual returns (uint256) {
return type(uint256).max;
}
/**
* @dev Optional function for a strategist to override that will
* allow management to manually withdraw deployed funds from the
* yield source if a strategy is shutdown.
*
* This should attempt to free `_amount`, noting that `_amount` may
* be more than is currently deployed.
*
* NOTE: This will not realize any profits or losses. A separate
* {report} will be needed in order to record any profit/loss. If
* a report may need to be called after a shutdown it is important
* to check if the strategy is shutdown during {_harvestAndReport}
* so that it does not simply re-deploy all funds that had been freed.
*
* EX:
* if(freeAsset > 0 && !TokenizedStrategy.isShutdown()) {
* depositFunds...
* }
*
* @param _amount The amount of asset to attempt to free.
*/
function _emergencyWithdraw(uint256 _amount) internal virtual {}
/*//////////////////////////////////////////////////////////////
TokenizedStrategy HOOKS
//////////////////////////////////////////////////////////////*/
/**
* @notice Can deploy up to '_amount' of 'asset' in yield source.
* @dev Callback for the TokenizedStrategy to call during a {deposit}
* or {mint} to tell the strategy it can deploy funds.
*
* Since this can only be called after a {deposit} or {mint}
* delegateCall to the TokenizedStrategy msg.sender == address(this).
*
* Unless a whitelist is implemented this will be entirely permissionless
* and thus can be sandwiched or otherwise manipulated.
*
* @param _amount The amount of 'asset' that the strategy can
* attempt to deposit in the yield source.
*/
function deployFunds(uint256 _amount) external virtual onlySelf {
_deployFunds(_amount);
}
/**
* @notice Should attempt to free the '_amount' of 'asset'.
* @dev Callback for the TokenizedStrategy to call during a withdraw
* or redeem to free the needed funds to service the withdraw.
*
* This can only be called after a 'withdraw' or 'redeem' delegateCall
* to the TokenizedStrategy so msg.sender == address(this).
*
* @param _amount The amount of 'asset' that the strategy should attempt to free up.
*/
function freeFunds(uint256 _amount) external virtual onlySelf {
_freeFunds(_amount);
}
/**
* @notice Returns the accurate amount of all funds currently
* held by the Strategy.
* @dev Callback for the TokenizedStrategy to call during a report to
* get an accurate accounting of assets the strategy controls.
*
* This can only be called after a report() delegateCall to the
* TokenizedStrategy so msg.sender == address(this).
*
* @return . A trusted and accurate account for the total amount
* of 'asset' the strategy currently holds including idle funds.
*/
function harvestAndReport() external virtual onlySelf returns (uint256) {
return _harvestAndReport();
}
/**
* @notice Will call the internal '_tend' when a keeper tends the strategy.
* @dev Callback for the TokenizedStrategy to initiate a _tend call in the strategy.
*
* This can only be called after a tend() delegateCall to the TokenizedStrategy
* so msg.sender == address(this).
*
* We name the function `tendThis` so that `tend` calls are forwarded to
* the TokenizedStrategy.
* @param _totalIdle The amount of current idle funds that can be
* deployed during the tend
*/
function tendThis(uint256 _totalIdle) external virtual onlySelf {
_tend(_totalIdle);
}
/**
* @notice Will call the internal '_emergencyWithdraw' function.
* @dev Callback for the TokenizedStrategy during an emergency withdraw.
*
* This can only be called after a emergencyWithdraw() delegateCall to
* the TokenizedStrategy so msg.sender == address(this).
*
* We name the function `shutdownWithdraw` so that `emergencyWithdraw`
* calls are forwarded to the TokenizedStrategy.
*
* @param _amount The amount of asset to attempt to free.
*/
function shutdownWithdraw(uint256 _amount) external virtual onlySelf {
_emergencyWithdraw(_amount);
}
/**
* @dev Function used to delegate call the TokenizedStrategy with
* certain `_calldata` and return any return values.
*
* This is used to setup the initial storage of the strategy, and
* can be used by strategist to forward any other call to the
* TokenizedStrategy implementation.
*
* @param _calldata The abi encoded calldata to use in delegatecall.
* @return . The return value if the call was successful in bytes.
*/
function _delegateCall(
bytes memory _calldata
) internal returns (bytes memory) {
// Delegate call the tokenized strategy with provided calldata.
(bool success, bytes memory result) = tokenizedStrategyAddress
.delegatecall(_calldata);
// If the call reverted. Return the error.
if (!success) {
assembly {
let ptr := mload(0x40)
let size := returndatasize()
returndatacopy(ptr, 0, size)
revert(ptr, size)
}
}
// Return the result.
return result;
}
/**
* @dev Execute a function on the TokenizedStrategy and return any value.
*
* This fallback function will be executed when any of the standard functions
* defined in the TokenizedStrategy are called since they wont be defined in
* this contract.
*
* It will delegatecall the TokenizedStrategy implementation with the exact
* calldata and return any relevant values.
*
*/
fallback() external {
// load our target address
address _tokenizedStrategyAddress = tokenizedStrategyAddress;
// Execute external function using delegatecall and return any value.
assembly {
// Copy function selector and any arguments.
calldatacopy(0, 0, calldatasize())
// Execute function delegatecall.
let result := delegatecall(
gas(),
_tokenizedStrategyAddress,
0,
calldatasize(),
0,
0
)
// Get any return value
returndatacopy(0, 0, returndatasize())
// Return any return value or error back to the caller
switch result
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
}
// src/SuperVault.sol
/// @title SuperVault
/// @notice A vault contract that manages multiple Superform positions
/// @dev Inherits from BaseStrategy and implements ISuperVault and IERC1155Receiver
/// @author Superform Labs
contract SuperVault is BaseStrategy, ISuperVault {
using EnumerableSet for EnumerableSet.UintSet;
using SafeERC20 for IERC20;
using SafeERC20 for ERC20;
using DataLib for uint256;
using Math for uint256;
//////////////////////////////////////////////////////////////
// STATE VARIABLES //
//////////////////////////////////////////////////////////////
/// @notice The chain ID of the network this contract is deployed on
uint64 public immutable CHAIN_ID;
/// @notice The address of the SuperVault Strategist
address public strategist;
/// @notice The address of the SuperVault Vault Manager
address public vaultManager;
/// @notice The address of the SuperRegistry contract
ISuperRegistry public immutable superRegistry;
/// @notice The address of the SuperformFactory contract
ISuperformFactory public immutable superformFactory;
/// @notice The ID of the ERC5115 form implementation
uint32 public ERC5115FormImplementationId;
/// @notice The total weight used for calculating proportions (10000 = 100%)
uint256 private constant TOTAL_WEIGHT = 10_000;
/// @notice The maximum allowed slippage (1% = 100)
uint256 private constant MAX_SLIPPAGE = 100;
/// @dev Tolerance constant to account for minAmountOut check in 5115
uint256 private constant TOLERANCE_CONSTANT = 10 wei;
/// @notice The number of Superforms in the vault
uint256 public numberOfSuperforms;
/// @notice The deposit limit for the vault
uint256 public depositLimit;
/// @notice Set of whitelisted Superform IDs for easy access
EnumerableSet.UintSet whitelistedSuperformIdsSet;
/// @notice Array of Superform IDs in the vault
uint256[] public superformIds;
/// @notice Array of weights for each Superform in the vault
uint256[] public weights;
address private immutable _SUPER_POSITIONS;
address private immutable _SUPERFORM_ROUTER;
address private immutable _SUPERFORM_FACTORY;
/// @notice Slot for call depth.
/// @dev Equal to bytes32(uint256(keccak256("transient.calldepth")) - 1).
bytes32 internal constant CALL_DEPTH_SLOT = 0x7a74fd168763fd280eaec3bcd2fd62d0e795027adc8183a693c497a7c2b10b5c;
//////////////////////////////////////////////////////////////
// MODIFIERS //
//////////////////////////////////////////////////////////////
/// @notice Ensures that only the Super Vaults Strategist can call the function
modifier onlySuperVaultsStrategist() {
if (strategist != msg.sender) {
revert NOT_SUPER_VAULTS_STRATEGIST();
}
_;
}
/// @notice Ensures that only the Vault Manager can call the function
modifier onlyVaultManager() {
if (vaultManager != msg.sender) {
revert NOT_VAULT_MANAGER();
}
_;
}
//////////////////////////////////////////////////////////////
// CONSTRUCTOR //
//////////////////////////////////////////////////////////////
/// @param superRegistry_ Address of the SuperRegistry contract
/// @param asset_ Address of the asset token
/// @param name_ Name of the strategy
/// @param depositLimit_ Maximum deposit limit
/// @param superformIds_ Array of Superform IDs
/// @param startingWeights_ Array of starting weights for each Superform
constructor(
address superRegistry_,
address asset_,
address strategist_,
address vaultManager_,
string memory name_,
uint256 depositLimit_,
uint256[] memory superformIds_,
uint256[] memory startingWeights_
)
BaseStrategy(asset_, name_)
{
numberOfSuperforms = superformIds_.length;
if (numberOfSuperforms == 0) {
revert ZERO_SUPERFORMS();
}
if (numberOfSuperforms != startingWeights_.length) {
revert ARRAY_LENGTH_MISMATCH();
}
if (superRegistry_ == address(0) || strategist_ == address(0) || vaultManager_ == address(0)) {
revert ZERO_ADDRESS();
}
superRegistry = ISuperRegistry(superRegistry_);
superformFactory = ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY")));
if (CHAIN_ID > type(uint64).max) {
revert BLOCK_CHAIN_ID_OUT_OF_BOUNDS();
}
CHAIN_ID = uint64(block.chainid);
uint256 totalWeight;
address superform;
for (uint256 i; i < numberOfSuperforms; ++i) {
/// @dev this superVault only supports superforms that have the same asset as the vault
(superform,,) = superformIds_[i].getSuperform();
if (!superformFactory.isSuperform(superformIds_[i])) {
revert SUPERFORM_DOES_NOT_EXIST(superformIds_[i]);
}
if (IBaseForm(superform).getVaultAsset() != asset_) {
revert SUPERFORM_DOES_NOT_SUPPORT_ASSET();
}
/// @dev initial whitelist of superform IDs
_addToWhitelist(superformIds_[i]);
totalWeight += startingWeights_[i];
}
if (totalWeight != TOTAL_WEIGHT) revert INVALID_WEIGHTS();
strategist = strategist_;
vaultManager = vaultManager_;
superformIds = superformIds_;
weights = startingWeights_;
depositLimit = depositLimit_;
{
_SUPER_POSITIONS = _getAddress(keccak256("SUPER_POSITIONS"));
_SUPERFORM_ROUTER = _getAddress(keccak256("SUPERFORM_ROUTER"));
_SUPERFORM_FACTORY = _getAddress(keccak256("SUPERFORM_FACTORY"));
}
}
//////////////////////////////////////////////////////////////
// EXTERNAL FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @inheritdoc ISuperVault
function setDepositLimit(uint256 depositLimit_) external override onlyVaultManager {
depositLimit = depositLimit_;
emit DepositLimitSet(depositLimit_);
}
/// @inheritdoc ISuperVault
function setStrategist(address strategist_) external override onlyManagement {
strategist = strategist_;
emit StrategistSet(strategist_);
}
/// @inheritdoc ISuperVault
function setValid5115FormImplementationId(uint32 formImplementationId_) external override onlyManagement {
if (formImplementationId_ == 0) revert ZERO_ID();
ERC5115FormImplementationId = formImplementationId_;
}
/// @inheritdoc ISuperVault
function rebalance(RebalanceArgs calldata rebalanceArgs_) external payable override onlySuperVaultsStrategist {
uint256 lenRebalanceFrom = rebalanceArgs_.superformIdsRebalanceFrom.length;
uint256 lenAmountsRebalanceFrom = rebalanceArgs_.amountsRebalanceFrom.length;
uint256 lenFinal = rebalanceArgs_.finalSuperformIds.length;
if (lenAmountsRebalanceFrom == 0) revert EMPTY_AMOUNTS_REBALANCE_FROM();
if (lenFinal == 0) revert EMPTY_FINAL_SUPERFORM_IDS();
/// @dev sanity check input arrays
if (lenRebalanceFrom != lenAmountsRebalanceFrom || lenFinal != rebalanceArgs_.weightsOfRedestribution.length) {
revert ARRAY_LENGTH_MISMATCH();
}
{
/// @dev caching to avoid multiple loads
uint256 foundCount;
uint256 nSuperforms = numberOfSuperforms;
for (uint256 i; i < lenRebalanceFrom; ++i) {
for (uint256 j; j < nSuperforms; ++j) {
if (rebalanceArgs_.superformIdsRebalanceFrom[i] == superformIds[j]) {
foundCount++;
break;
}
}
}
if (foundCount != lenRebalanceFrom) {
revert INVALID_SUPERFORM_ID_REBALANCE_FROM();
}
}
for (uint256 i = 1; i < lenRebalanceFrom; ++i) {
if (rebalanceArgs_.superformIdsRebalanceFrom[i] <= rebalanceArgs_.superformIdsRebalanceFrom[i - 1]) {
revert DUPLICATE_SUPERFORM_IDS_REBALANCE_FROM();
}
}
for (uint256 i; i < lenFinal; ++i) {
if (i >= 1 && rebalanceArgs_.finalSuperformIds[i] <= rebalanceArgs_.finalSuperformIds[i - 1]) {
revert DUPLICATE_FINAL_SUPERFORM_IDS();
}
if (!whitelistedSuperformIdsSet.contains(rebalanceArgs_.finalSuperformIds[i])) {
revert SUPERFORM_NOT_WHITELISTED();
}
}
/// @dev step 1: prepare rebalance arguments
ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args = _prepareRebalanceArgs(
rebalanceArgs_.superformIdsRebalanceFrom,
rebalanceArgs_.amountsRebalanceFrom,
rebalanceArgs_.finalSuperformIds,
rebalanceArgs_.weightsOfRedestribution,
rebalanceArgs_.slippage
);
address routerPlus = _getAddress(keccak256("SUPERFORM_ROUTER_PLUS"));
/// @dev step 2: execute rebalance
_setSuperPositionsApproval(routerPlus, args.ids, args.sharesToRedeem);
ISuperformRouterPlus(routerPlus).rebalanceMultiPositions(args);
/// @dev step 3: update SV data
/// @notice no issue about reentrancy as the external contracts are trusted
/// @notice updateSV emits rebalance event
_updateSVData(_SUPER_POSITIONS, rebalanceArgs_.finalSuperformIds);
}
/// @inheritdoc ISuperVault
function forwardDustToPaymaster() external override {
address paymaster = superRegistry.getAddress(keccak256("PAYMASTER"));
IERC20 token = IERC20(asset);
uint256 dust = _getAssetBalance(token);
if (dust != 0) {
token.safeTransfer(paymaster, dust);
emit DustForwardedToPaymaster(dust);
}
}
/// @inheritdoc ISuperVault
function setWhitelist(
uint256[] memory superformIds_,
bool[] memory isWhitelisted_
)
external
override
onlyVaultManager
{
uint256 length = superformIds_.length;
if (length != isWhitelisted_.length) revert ARRAY_LENGTH_MISMATCH();
if (length == 0) revert ZERO_SUPERFORMS();
for (uint256 i; i < length; ++i) {
_changeSuperformWhitelist(superformIds_[i], isWhitelisted_[i]);
}
}
/// @inheritdoc ISuperVault
function setVaultManager(address vaultManager_) external override onlyManagement {
if (vaultManager_ == address(0)) revert ZERO_ADDRESS();
vaultManager = vaultManager_;
emit VaultManagerSet(vaultManager_);
}
//////////////////////////////////////////////////////////////
// EXTERNAL VIEW/PURE FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @inheritdoc ISuperVault
function getIsWhitelisted(uint256[] memory superformIds_) external view returns (bool[] memory isWhitelisted) {
uint256 length = superformIds_.length;
isWhitelisted = new bool[](length);
for (uint256 i; i < length; ++i) {
isWhitelisted[i] = whitelistedSuperformIdsSet.contains(superformIds_[i]);
}
return isWhitelisted;
}
/// @inheritdoc ISuperVault
function getWhitelist() external view override returns (uint256[] memory) {
return whitelistedSuperformIdsSet.values();
}
/// @inheritdoc ISuperVault
function getSuperVaultData() external view returns (uint256[] memory superformIds_, uint256[] memory weights_) {
return (superformIds, weights);
}
/// @inheritdoc IERC1155Receiver
function onERC1155Received(
address,
address,
uint256,
uint256,
bytes calldata
)
external
pure
override
returns (bytes4)
{
return this.onERC1155Received.selector;
}
/// @inheritdoc IERC1155Receiver
function onERC1155BatchReceived(
address,
address,
uint256[] calldata,
uint256[] calldata,
bytes calldata
)
external
pure
override
returns (bytes4)
{
return this.onERC1155BatchReceived.selector;
}
/// @notice Checks if the contract supports a given interface
/// @param interfaceId The interface identifier
/// @return bool True if the contract supports the interface
function supportsInterface(bytes4 interfaceId) external pure override returns (bool) {
return interfaceId == type(IERC165_1).interfaceId || interfaceId == type(IERC1155Receiver).interfaceId;
}
/// @inheritdoc BaseStrategy
function availableDepositLimit(address /*_owner*/ ) public view override returns (uint256) {
uint256 totalAssets = TokenizedStrategy.totalAssets();
uint256 _depositLimit_ = depositLimit;
return totalAssets >= _depositLimit_ ? 0 : _depositLimit_ - totalAssets;
}
//////////////////////////////////////////////////////////////
// BASESTRATEGY INTERNAL OVERRIDES //
//////////////////////////////////////////////////////////////
/// @notice Deploys funds to the underlying Superforms
/// @param amount_ The amount of funds to deploy
function _deployFunds(uint256 amount_) internal override {
bytes memory callData = numberOfSuperforms == 1
? abi.encodeWithSelector(
IBaseRouter.singleDirectSingleVaultDeposit.selector,
SingleDirectSingleVaultStateReq(_prepareSingleVaultDepositData(amount_))
)
: abi.encodeWithSelector(
IBaseRouter.singleDirectMultiVaultDeposit.selector,
SingleDirectMultiVaultStateReq(_prepareMultiVaultDepositData(amount_))
);
address router = _SUPERFORM_ROUTER;
asset.safeIncreaseAllowance(router, amount_);
/// @dev this call has to be enforced with 0 msg.value not to break the 4626 standard
(bool success, bytes memory returndata) = router.call(callData);
Address_1.verifyCallResult(success, returndata, "CallRevertWithNoReturnData");
if (asset.allowance(address(this), router) > 0) asset.forceApprove(router, 0);
}
/// @notice Frees funds from the underlying Superforms
/// @param amount_ The amount of funds to free
function _freeFunds(uint256 amount_) internal override {
bytes memory callData;
address router = _SUPERFORM_ROUTER;
if (numberOfSuperforms == 1) {
SingleVaultSFData memory svData = _prepareSingleVaultWithdrawData(amount_);
callData = abi.encodeWithSelector(
IBaseRouter.singleDirectSingleVaultWithdraw.selector, SingleDirectSingleVaultStateReq(svData)
);
_setSuperPositionApproval(router, svData.superformId, svData.amount);
} else {
MultiVaultSFData memory mvData = _prepareMultiVaultWithdrawData(amount_);
callData = abi.encodeWithSelector(
IBaseRouter.singleDirectMultiVaultWithdraw.selector, SingleDirectMultiVaultStateReq(mvData)
);
_setSuperPositionsApproval(router, mvData.superformIds, mvData.amounts);
}
/// @dev this call has to be enforced with 0 msg.value not to break the 4626 standard
(bool success, bytes memory returndata) = router.call(callData);
Address_1.verifyCallResult(success, returndata, "CallRevertWithNoReturnData");
}
/// @notice Reports the total assets of the vault
/// @return totalAssets The total assets of the vault
function _harvestAndReport() internal view override returns (uint256 totalAssets) {
uint256 totalAssetsInVaults;
uint256 _numberOfSuperforms_ = numberOfSuperforms;
uint256[] memory _superformIds_ = superformIds;
address superPositions = _SUPER_POSITIONS;
for (uint256 i; i < _numberOfSuperforms_;) {
(address superform,,) = _superformIds_[i].getSuperform();
/// @dev This contract holds superPositions, not shares
uint256 spBalance = ISuperPositions(superPositions).balanceOf(address(this), _superformIds_[i]);
totalAssetsInVaults += IBaseForm(superform).previewRedeemFrom(spBalance);
unchecked {
++i;
}
}
totalAssets = totalAssetsInVaults + _getAssetBalance(asset);
}
//////////////////////////////////////////////////////////////
// INTERNAL FUNCTIONS //
//////////////////////////////////////////////////////////////
function _prepareMultiVaultDepositData(uint256 amount_) internal view returns (MultiVaultSFData memory mvData) {
uint256 _numberOfSuperforms_ = numberOfSuperforms;
mvData.superformIds = superformIds;
mvData.amounts = new uint256[](_numberOfSuperforms_);
mvData.maxSlippages = new uint256[](_numberOfSuperforms_);
mvData.liqRequests = new LiqRequest[](_numberOfSuperforms_);
mvData.hasDstSwaps = new bool[](_numberOfSuperforms_);
mvData.retain4626s = mvData.hasDstSwaps;
mvData.receiverAddress = address(this);
mvData.receiverAddressSP = address(this);
mvData.outputAmounts = new uint256[](_numberOfSuperforms_);
bytes[] memory dataToEncode = new bytes[](_numberOfSuperforms_);
uint256[] memory _weights_ = weights;
for (uint256 i; i < _numberOfSuperforms_;) {
mvData.liqRequests[i].token = address(asset);
(address superform,,) = mvData.superformIds[i].getSuperform();
dataToEncode[i] = _prepareDepositExtraFormDataForSuperform(mvData.superformIds[i]);
/// @notice rounding down to avoid one-off issue
mvData.amounts[i] = amount_.mulDiv(_weights_[i], TOTAL_WEIGHT, Math.Rounding.Down);
mvData.outputAmounts[i] = IBaseForm(superform).previewDepositTo(mvData.amounts[i]);
mvData.maxSlippages[i] = MAX_SLIPPAGE;
unchecked {
++i;
}
}
mvData.extraFormData = abi.encode(_numberOfSuperforms_, dataToEncode);
return mvData;
}
function _prepareSingleVaultDepositData(uint256 amount_) internal view returns (SingleVaultSFData memory svData) {
svData.superformId = superformIds[0];
svData.amount = amount_;
svData.maxSlippage = MAX_SLIPPAGE;
svData.liqRequest.token = address(asset);
svData.hasDstSwap = false;
svData.retain4626 = false;
svData.receiverAddress = address(this);
svData.receiverAddressSP = address(this);
(address superform,,) = svData.superformId.getSuperform();
svData.outputAmount = IBaseForm(superform).previewDepositTo(amount_);
bytes memory dataToEncode = _prepareDepositExtraFormDataForSuperform(svData.superformId);
bytes[] memory finalDataToEncode = new bytes[](1);
finalDataToEncode[0] = dataToEncode;
svData.extraFormData = abi.encode(1, finalDataToEncode);
return svData;
}
function _prepareMultiVaultWithdrawData(uint256 amount_) internal view returns (MultiVaultSFData memory mvData) {
uint256 _numberOfSuperforms_ = numberOfSuperforms;
mvData.superformIds = superformIds;
mvData.amounts = new uint256[](_numberOfSuperforms_);
mvData.maxSlippages = new uint256[](_numberOfSuperforms_);
mvData.liqRequests = new LiqRequest[](_numberOfSuperforms_);
mvData.hasDstSwaps = new bool[](_numberOfSuperforms_);
mvData.retain4626s = mvData.hasDstSwaps;
mvData.receiverAddress = address(this);
mvData.receiverAddressSP = address(this);
mvData.outputAmounts = new uint256[](_numberOfSuperforms_);
address superPositions = _SUPER_POSITIONS;
uint256 totalAssetsInVaults;
uint256[] memory spBalances = new uint256[](_numberOfSuperforms_);
uint256[] memory assetBalances = new uint256[](_numberOfSuperforms_);
// Snapshot assets and SP balances
for (uint256 i; i < _numberOfSuperforms_;) {
(address superform,,) = mvData.superformIds[i].getSuperform();
spBalances[i] = _getSuperPositionBalance(superPositions, mvData.superformIds[i]);
assetBalances[i] = IBaseForm(superform).previewRedeemFrom(spBalances[i]);
totalAssetsInVaults += assetBalances[i];
unchecked {
++i;
}
}
// Calculate withdrawal amounts
for (uint256 i; i < _numberOfSuperforms_;) {
mvData.liqRequests[i].token = address(asset);
(address superform,,) = mvData.superformIds[i].getSuperform();
bool isERC5115 = _isERC5115Vault(mvData.superformIds[i]);
if (isERC5115) {
mvData.liqRequests[i].interimToken = address(asset);
}
if (amount_ >= totalAssetsInVaults) {
mvData.amounts[i] = spBalances[i];
mvData.outputAmounts[i] = _tolerance(isERC5115, assetBalances[i]);
} else {
uint256 amountOut = amount_.mulDiv(weights[i], TOTAL_WEIGHT, Math.Rounding.Down);
mvData.outputAmounts[i] = _tolerance(isERC5115, amountOut);
mvData.amounts[i] = IBaseForm(superform).previewDepositTo(amountOut);
if (mvData.amounts[i] > spBalances[i]) {
mvData.amounts[i] = spBalances[i];
}
}
mvData.maxSlippages[i] = MAX_SLIPPAGE;
unchecked {
++i;
}
}
return mvData;
}
function _prepareSingleVaultWithdrawData(uint256 amount_) internal view returns (SingleVaultSFData memory svData) {
svData.superformId = superformIds[0];
(address superform,,) = svData.superformId.getSuperform();
// Get current balances
uint256 spBalance = _getSuperPositionBalance(_SUPER_POSITIONS, svData.superformId);
uint256 assetBalance = IBaseForm(superform).previewRedeemFrom(spBalance);
// Set up basic data
svData.liqRequest.token = address(asset);
bool isERC5115 = _isERC5115Vault(svData.superformId);
if (isERC5115) {
svData.liqRequest.interimToken = address(asset);
}
// Calculate withdrawal amounts
if (amount_ >= assetBalance) {
svData.amount = spBalance;
svData.outputAmount = _tolerance(isERC5115, assetBalance);
} else {
svData.outputAmount = _tolerance(isERC5115, amount_);
svData.amount = IBaseForm(superform).previewDepositTo(amount_);
if (svData.amount > spBalance) {
svData.amount = spBalance;
}
}
svData.maxSlippage = MAX_SLIPPAGE;
svData.hasDstSwap = false;
svData.retain4626 = false;
svData.receiverAddress = address(this);
svData.receiverAddressSP = address(this);
return svData;
}
/// @notice Checks if a vault is ERC5115 and validates form implementation IDs
/// @param superformId_ The superform ID to check
/// @return isERC5115 True if the vault is ERC5115
function _isERC5115Vault(uint256 superformId_) internal view returns (bool isERC5115) {
ISuperformFactoryMinimal factory = ISuperformFactoryMinimal(_SUPERFORM_FACTORY);
address erc5115Implementation = factory.getFormImplementation(ERC5115FormImplementationId);
(address superform,,) = superformId_.getSuperform();
uint256 superFormId = factory.vaultFormImplCombinationToSuperforms(
keccak256(abi.encode(erc5115Implementation, IBaseForm(superform).getVaultAddress()))
);
if (superFormId == superformId_) {
isERC5115 = true;
}
}
/// @dev returns the address for id_ from super registry
function _getAddress(bytes32 id_) internal view returns (address) {
return superRegistry.getAddress(id_);
}
/// @notice Sets approval for multiple SuperPositions
/// @param router_ The router address to approve
/// @param superformIds_ The superform IDs to approve
/// @param amounts_ The amounts to approve
function _setSuperPositionsApproval(
address router_,
uint256[] memory superformIds_,
uint256[] memory amounts_
)
internal
{
ISuperPositions(_SUPER_POSITIONS).setApprovalForMany(router_, superformIds_, amounts_);
}
/// @notice Sets approval for a single SuperPosition
/// @param router_ The router address to approve
/// @param superformId_ The superform ID to approve
/// @param amount_ The amount to approve
function _setSuperPositionApproval(address router_, uint256 superformId_, uint256 amount_) internal {
ISuperPositions(_SUPER_POSITIONS).setApprovalForOne(router_, superformId_, amount_);
}
/// @notice Gets the current balance of the asset token held by this contract
/// @return balance The current balance of the asset token
function _getAssetBalance(IERC20 token_) internal view returns (uint256) {
return token_.balanceOf(address(this));
}
function _getSuperPositionBalance(address superPositions, uint256 superformId) internal view returns (uint256) {
return ISuperPositions(superPositions).balanceOf(address(this), superformId);
}
/// @notice Prepares rebalance arguments for Superform Router Plus
/// @param superformIdsRebalanceFrom_ Array of Superform IDs to rebalance from
/// @param amountsRebalanceFrom_ Array of amounts to rebalance from
/// @param finalSuperformIds_ Array of Superform IDs to rebalance to
/// @param weightsOfRedestribution_ Array of weights for redestribution
/// @param slippage_ Maximum allowed slippage
function _prepareRebalanceArgs(
uint256[] calldata superformIdsRebalanceFrom_,
uint256[] calldata amountsRebalanceFrom_,
uint256[] calldata finalSuperformIds_,
uint256[] calldata weightsOfRedestribution_,
uint256 slippage_
)
internal
view
returns (ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args)
{
args.ids = superformIdsRebalanceFrom_;
args.sharesToRedeem = amountsRebalanceFrom_;
args.interimAsset = address(asset); // Assuming 'asset' is the interim token
args.slippage = slippage_; // 1% slippage, adjust as needed
args.receiverAddressSP = address(this);
(SingleDirectMultiVaultStateReq memory req, uint256 totalOutputAmount) =
_prepareSingleDirectMultiVaultStateReq(superformIdsRebalanceFrom_, amountsRebalanceFrom_, slippage_, true);
/// @dev prepare callData for rebalance from
args.callData = abi.encodeWithSelector(IBaseRouter.singleDirectMultiVaultWithdraw.selector, req);
/// @dev create a filtered version of superformIdsRebalanceTo
(uint256[] memory filteredSuperformIds, uint256[] memory filteredWeights) =
_filterNonZeroWeights(finalSuperformIds_, weightsOfRedestribution_);
(req,) = _prepareSingleDirectMultiVaultStateReq(
filteredSuperformIds, _calculateAmounts(totalOutputAmount, filteredWeights), slippage_, false
);
/// @dev prepare rebalanceToCallData
args.rebalanceToCallData = abi.encodeWithSelector(IBaseRouter.singleDirectMultiVaultDeposit.selector, req);
args.expectedAmountToReceivePostRebalanceFrom = totalOutputAmount;
}
/// @notice Prepares single direct multi-vault state request
/// @param superformIds_ Array of Superform IDs
/// @param amounts_ Array of amounts
/// @param slippage_ Maximum allowed slippage
/// @param isWithdraw_ True if withdrawing, false if depositing
/// @return req The prepared single direct multi-vault state request
/// @return totalOutputAmount The total output amount
function _prepareSingleDirectMultiVaultStateReq(
uint256[] memory superformIds_,
uint256[] memory amounts_,
uint256 slippage_,
bool isWithdraw_
)
internal
view
returns (SingleDirectMultiVaultStateReq memory req, uint256 totalOutputAmount)
{
MultiVaultSFData memory data;
data.superformIds = superformIds_;
data.amounts = amounts_;
address routerPlus = _getAddress(keccak256("SUPERFORM_ROUTER_PLUS"));
uint256 _numberOfSuperforms_ = superformIds_.length;
data.outputAmounts = new uint256[](_numberOfSuperforms_);
data.maxSlippages = new uint256[](_numberOfSuperforms_);
data.liqRequests = new LiqRequest[](_numberOfSuperforms_);
bytes[] memory dataToEncode = new bytes[](_numberOfSuperforms_);
for (uint256 i; i < _numberOfSuperforms_;) {
(address superform,,) = superformIds_[i].getSuperform();
if (isWithdraw_) {
// Check if vault is ERC5115
bool isERC5115 = _isERC5115Vault(superformIds_[i]);
if (isERC5115) {
data.liqRequests[i].interimToken = address(asset);
}
uint256 amountOut = IBaseForm(superform).previewRedeemFrom(amounts_[i]);
data.outputAmounts[i] = _tolerance(isERC5115, amountOut);
} else {
dataToEncode[i] = _prepareDepositExtraFormDataForSuperform(superformIds_[i]);
data.outputAmounts[i] = IBaseForm(superform).previewDepositTo(amounts_[i]);
}
totalOutputAmount += data.outputAmounts[i];
data.maxSlippages[i] = slippage_;
data.liqRequests[i].token = address(asset);
data.liqRequests[i].liqDstChainId = CHAIN_ID;
unchecked {
++i;
}
}
data.hasDstSwaps = new bool[](_numberOfSuperforms_);
data.retain4626s = data.hasDstSwaps;
/// @dev routerPlus receives assets to continue the rebalance
data.receiverAddress = routerPlus;
/// @dev in case of withdraw failure, this vault receives the superPositions back
data.receiverAddressSP = address(this);
if (!isWithdraw_) {
data.extraFormData = abi.encode(_numberOfSuperforms_, dataToEncode);
}
req.superformData = data;
}
/// @notice Prepares deposit extra form data for a single superform
/// @param superformId_ The superform ID
/// @return bytes Encoded data for the superform
function _prepareDepositExtraFormDataForSuperform(uint256 superformId_) internal view returns (bytes memory) {
// For ERC4626 vaults, no extra data needed
// For ERC5115 vaults, include asset address
bytes memory extraData = _isERC5115Vault(superformId_) ? abi.encode(address(asset)) : bytes("");
return abi.encode(superformId_, extraData);
}
/// @notice Calculates amounts based on total output amount and weights
/// @param totalOutputAmount_ The total output amount
/// @param weights_ Array of weights
/// @return amounts Array of calculated amounts
function _calculateAmounts(
uint256 totalOutputAmount_,
uint256[] memory weights_
)
internal
pure
returns (uint256[] memory amounts)
{
amounts = new uint256[](weights_.length);
for (uint256 i; i < weights_.length; ++i) {
amounts[i] = totalOutputAmount_.mulDiv(weights_[i], TOTAL_WEIGHT, Math.Rounding.Down);
}
}
/// @notice Filters out zero weights and returns corresponding superform IDs and weights
/// @param superformIds_ Array of Superform IDs
/// @param weights_ Array of weights
/// @return filteredIds Array of filtered Superform IDs
/// @return filteredWeights Array of filtered weights
function _filterNonZeroWeights(
uint256[] calldata superformIds_,
uint256[] calldata weights_
)
internal
pure
returns (uint256[] memory filteredIds, uint256[] memory filteredWeights)
{
uint256 count;
uint256 length = weights_.length;
for (uint256 i; i < length; ++i) {
if (weights_[i] != 0) {
count++;
}
}
filteredIds = new uint256[](count);
filteredWeights = new uint256[](count);
uint256 j;
uint256 totalWeight;
for (uint256 i; i < length; ++i) {
if (weights_[i] != 0) {
filteredIds[j] = superformIds_[i];
filteredWeights[j] = weights_[i];
totalWeight += weights_[i];
j++;
}
}
if (totalWeight != TOTAL_WEIGHT) revert INVALID_WEIGHTS();
}
/// @notice Updates the SuperVault data after rebalancing
/// @param superPositions_ Address of the SuperPositions contract
/// @param finalSuperformIds_ Array of Superform IDs to rebalance to
function _updateSVData(address superPositions_, uint256[] memory finalSuperformIds_) internal {
// Cache current superform IDs
uint256[] memory currentSuperformIds = superformIds;
// For each current superform ID
uint256 numSuperforms = currentSuperformIds.length;
uint256 numFinalSuperforms = finalSuperformIds_.length;
for (uint256 i; i < numSuperforms;) {
bool found;
// Check if it exists in finalSuperformIds_
for (uint256 j; j < numFinalSuperforms;) {
if (currentSuperformIds[i] == finalSuperformIds_[j]) {
found = true;
break;
}
unchecked {
++j;
}
}
// If not found in final IDs, it should be fully rebalanced
if (!found) {
if (_getSuperPositionBalance(superPositions_, currentSuperformIds[i]) != 0) {
revert INVALID_SP_FULL_REBALANCE(currentSuperformIds[i]);
}
}
unchecked {
++i;
}
}
uint256 totalWeight;
uint256 length = finalSuperformIds_.length;
if (length == 0) revert ZERO_SUPERFORMS();
uint256[] memory newWeights = new uint256[](length);
/// @dev check if finalSuperformIds are present in superform factory and support the asset
ISuperformFactory factory = ISuperformFactory(_SUPERFORM_FACTORY);
address superform;
uint256 value;
address assetCache = address(asset);
/// @dev calculate total value and individual values
for (uint256 i; i < length;) {
if (!factory.isSuperform(finalSuperformIds_[i])) {
revert SUPERFORM_DOES_NOT_EXIST(finalSuperformIds_[i]);
}
(superform,,) = finalSuperformIds_[i].getSuperform();
if (IBaseForm(superform).getVaultAsset() != assetCache) {
revert SUPERFORM_DOES_NOT_SUPPORT_ASSET();
}
uint256 balance = _getSuperPositionBalance(superPositions_, finalSuperformIds_[i]);
value = IBaseForm(superform).previewRedeemFrom(balance);
newWeights[i] = value;
totalWeight += value;
unchecked {
++i;
}
}
/// @dev calculate new weights as percentages
uint256 totalAssignedWeight;
for (uint256 i; i < length - 1;) {
newWeights[i] = newWeights[i].mulDiv(TOTAL_WEIGHT, totalWeight, Math.Rounding.Down);
totalAssignedWeight += newWeights[i];
unchecked {
++i;
}
}
/// @notice assign remaining weight to the last index
newWeights[length - 1] = TOTAL_WEIGHT - totalAssignedWeight;
/// @dev update SV data
weights = newWeights;
superformIds = finalSuperformIds_;
numberOfSuperforms = length;
emit RebalanceComplete(finalSuperformIds_, newWeights);
}
/// @notice Changes the whitelist for a Superform ID
/// @param superformId_ The Superform ID to change
/// @param isWhitelisted_ Whether to whitelist or blacklist
function _changeSuperformWhitelist(uint256 superformId_, bool isWhitelisted_) internal {
bool currentlyWhitelisted = whitelistedSuperformIdsSet.contains(superformId_);
// Only process if there's an actual change
if (currentlyWhitelisted != isWhitelisted_) {
if (isWhitelisted_) {
_addToWhitelist(superformId_);
} else {
_removeFromWhitelist(superformId_);
}
emit SuperformWhitelisted(superformId_, isWhitelisted_);
}
}
/// @notice Adds a superform ID to the whitelist array
/// @param superformId The Superform ID to add
function _addToWhitelist(uint256 superformId) internal {
whitelistedSuperformIdsSet.add(superformId);
}
/// @notice Removes a superform ID from the whitelist array
/// @param superformId The Superform ID to remove
function _removeFromWhitelist(uint256 superformId) internal {
whitelistedSuperformIdsSet.remove(superformId);
}
/// @notice Calculates the tolerance for ERC5115 vaults
/// @param isERC5115 Whether the vault is ERC5115
/// @param amount The amount to calculate tolerance for
/// @return The calculated tolerance
function _tolerance(bool isERC5115, uint256 amount) internal pure returns (uint256) {
return isERC5115 ? amount - TOLERANCE_CONSTANT : amount;
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"superRegistry_","type":"address"},{"internalType":"address","name":"asset_","type":"address"},{"internalType":"address","name":"strategist_","type":"address"},{"internalType":"address","name":"vaultManager_","type":"address"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"uint256","name":"depositLimit_","type":"uint256"},{"internalType":"uint256[]","name":"superformIds_","type":"uint256[]"},{"internalType":"uint256[]","name":"startingWeights_","type":"uint256[]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ARRAY_LENGTH_MISMATCH","type":"error"},{"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":"DUPLICATE_FINAL_SUPERFORM_IDS","type":"error"},{"inputs":[],"name":"DUPLICATE_SUPERFORM_IDS_REBALANCE_FROM","type":"error"},{"inputs":[],"name":"EMPTY_AMOUNTS_REBALANCE_FROM","type":"error"},{"inputs":[],"name":"EMPTY_FINAL_SUPERFORM_IDS","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"INVALID_CHAIN_ID","type":"error"},{"inputs":[{"internalType":"uint256","name":"superformId","type":"uint256"}],"name":"INVALID_SP_FULL_REBALANCE","type":"error"},{"inputs":[],"name":"INVALID_SUPERFORM_ID_REBALANCE_FROM","type":"error"},{"inputs":[],"name":"INVALID_WEIGHTS","type":"error"},{"inputs":[],"name":"NOT_PENDING_MANAGEMENT","type":"error"},{"inputs":[],"name":"NOT_SUPER_VAULTS_STRATEGIST","type":"error"},{"inputs":[],"name":"NOT_VAULT_MANAGER","type":"error"},{"inputs":[],"name":"REBALANCE_FROM_ID_NOT_FOUND_IN_FINAL_IDS","type":"error"},{"inputs":[{"internalType":"uint256","name":"superformId","type":"uint256"}],"name":"SUPERFORM_DOES_NOT_EXIST","type":"error"},{"inputs":[],"name":"SUPERFORM_DOES_NOT_SUPPORT_ASSET","type":"error"},{"inputs":[],"name":"SUPERFORM_NOT_WHITELISTED","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"ZERO_ADDRESS","type":"error"},{"inputs":[],"name":"ZERO_ID","type":"error"},{"inputs":[],"name":"ZERO_SUPERFORMS","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"depositLimit","type":"uint256"}],"name":"DepositLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"dust","type":"uint256"}],"name":"DustForwardedToPaymaster","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"finalSuperformIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"finalWeights","type":"uint256[]"}],"name":"RebalanceComplete","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"strategist","type":"address"}],"name":"StrategistSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"superformId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isWhitelisted","type":"bool"}],"name":"SuperformWhitelisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vaultManager","type":"address"}],"name":"VaultManagerSet","type":"event"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"CHAIN_ID","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC5115FormImplementationId","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"availableDepositLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"availableWithdrawLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deployFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"forwardDustToPaymaster","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"freeFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"superformIds_","type":"uint256[]"}],"name":"getIsWhitelisted","outputs":[{"internalType":"bool[]","name":"isWhitelisted","type":"bool[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSuperVaultData","outputs":[{"internalType":"uint256[]","name":"superformIds_","type":"uint256[]"},{"internalType":"uint256[]","name":"weights_","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWhitelist","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"harvestAndReport","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"numberOfSuperforms","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"uint256[]","name":"superformIdsRebalanceFrom","type":"uint256[]"},{"internalType":"uint256[]","name":"amountsRebalanceFrom","type":"uint256[]"},{"internalType":"uint256[]","name":"finalSuperformIds","type":"uint256[]"},{"internalType":"uint256[]","name":"weightsOfRedestribution","type":"uint256[]"},{"internalType":"uint256","name":"slippage","type":"uint256"}],"internalType":"struct ISuperVault.RebalanceArgs","name":"rebalanceArgs_","type":"tuple"}],"name":"rebalance","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"depositLimit_","type":"uint256"}],"name":"setDepositLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"strategist_","type":"address"}],"name":"setStrategist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"formImplementationId_","type":"uint32"}],"name":"setValid5115FormImplementationId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vaultManager_","type":"address"}],"name":"setVaultManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"superformIds_","type":"uint256[]"},{"internalType":"bool[]","name":"isWhitelisted_","type":"bool[]"}],"name":"setWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"shutdownWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"strategist","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"superRegistry","outputs":[{"internalType":"contract ISuperRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"superformFactory","outputs":[{"internalType":"contract ISuperformFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"superformIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_totalIdle","type":"uint256"}],"name":"tendThis","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tendTrigger","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenizedStrategyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"weights","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
61018060405234801562000011575f80fd5b5060405162005d2c38038062005d2c833981016040819052620000349162000915565b6001600160a01b0387166080523060a052604051879085906200009d90620000699084908490339081908190602401620009f4565b60408051601f198184030181529190526020810180516001600160e01b03908116634b839d7360e11b179091526200059616565b505073bb51273d6c746910c7c06fe718f30c936170fed07f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5550815160028190555f03620000fe576040516342c313c360e11b815260040160405180910390fd5b8051600254146200012257604051634456f5e960e11b815260040160405180910390fd5b6001600160a01b03881615806200014057506001600160a01b038616155b806200015357506001600160a01b038516155b15620001725760405163538ba4f960e01b815260040160405180910390fd5b6001600160a01b03881660e08190526040516321f8a72160e01b81527fbcc180fb907e9ae431665de4bc74305c00b7b27442aadd477980ecc4bb14c01160048201526321f8a72190602401602060405180830381865afa158015620001d9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620001ff919062000a4e565b6001600160a01b03166101005260c0516001600160401b0390811611156200023a57604051637ecdf93360e01b815260040160405180910390fd5b6001600160401b03461660c0525f80805b6002548110156200045957620002838582815181106200026f576200026f62000a6a565b60200260200101516200062560201b60201c565b90505080925050610100516001600160a01b031663b5c75697868381518110620002b157620002b162000a6a565b60200260200101516040518263ffffffff1660e01b8152600401620002d891815260200190565b602060405180830381865afa158015620002f4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200031a919062000a7e565b620003625784818151811062000334576200033462000a6a565b60200260200101516040516317ed28b560e31b81526004016200035991815260200190565b60405180910390fd5b896001600160a01b0316826001600160a01b031663b60262ca6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620003a9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620003cf919062000a4e565b6001600160a01b031614620003f7576040516307397cd760e01b815260040160405180910390fd5b6200042485828151811062000410576200041062000a6a565b60200260200101516200065960201b60201c565b83818151811062000439576200043962000a6a565b6020026020010151836200044e919062000a9f565b92506001016200024b565b5061271082146200047d576040516314ccf61760e31b815260040160405180910390fd5b5f80546001600160a01b03808b166001600160a01b03199283161790925560018054928a16929091169190911790558351620004c190600690602087019062000734565b508251620004d790600790602086019062000734565b506003859055620005087fba0b74768b1de73590a53e1384870dcbc846e5c73bab23c07d71eaa7cbf8411b6200066a565b6001600160a01b031661012052620005407f3a2f5529773e03d975be44bdae98a8509bdf1159e407504e558536cde56cf6ac6200066a565b6001600160a01b031661014052620005787fbcc180fb907e9ae431665de4bc74305c00b7b27442aadd477980ecc4bb14c0116200066a565b6001600160a01b0316610160525062000adc98505050505050505050565b60605f8073bb51273d6c746910c7c06fe718f30c936170fed06001600160a01b031684604051620005c8919062000abf565b5f60405180830381855af49150503d805f811462000602576040519150601f19603f3d011682016040523d82523d5f602084013e62000607565b606091505b5091509150816200061e576040513d805f833e8082fd5b9392505050565b8060a081901c60c082901c5f819003620006525760405163030042b760e01b815260040160405180910390fd5b9193909250565b62000666600482620006de565b5050565b60e0516040516321f8a72160e01b8152600481018390525f916001600160a01b0316906321f8a72190602401602060405180830381865afa158015620006b2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620006d8919062000a4e565b92915050565b5f6200061e83835f8181526001830160205260408120546200072c57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155620006d8565b505f620006d8565b828054828255905f5260205f2090810192821562000770579160200282015b828111156200077057825182559160200191906001019062000753565b506200077e92915062000782565b5090565b5b808211156200077e575f815560010162000783565b80516001600160a01b0381168114620007af575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715620007f357620007f3620007b4565b604052919050565b5f5b8381101562000817578181015183820152602001620007fd565b50505f910152565b5f82601f8301126200082f575f80fd5b81516001600160401b038111156200084b576200084b620007b4565b62000860601f8201601f1916602001620007c8565b81815284602083860101111562000875575f80fd5b62000888826020830160208701620007fb565b949350505050565b5f82601f830112620008a0575f80fd5b815160206001600160401b03821115620008be57620008be620007b4565b8160051b620008cf828201620007c8565b9283528481018201928281019087851115620008e9575f80fd5b83870192505b848310156200090a57825182529183019190830190620008ef565b979650505050505050565b5f805f805f805f80610100898b0312156200092e575f80fd5b620009398962000798565b97506200094960208a0162000798565b96506200095960408a0162000798565b95506200096960608a0162000798565b60808a01519095506001600160401b038082111562000986575f80fd5b620009948c838d016200081f565b955060a08b0151945060c08b0151915080821115620009b1575f80fd5b620009bf8c838d0162000890565b935060e08b0151915080821115620009d5575f80fd5b50620009e48b828c0162000890565b9150509295985092959890939650565b5f60018060a01b03808816835260a0602084015286518060a085015262000a238160c0860160208b01620007fb565b95811660408401529384166060830152509116608082015260c0601f909201601f1916010192915050565b5f6020828403121562000a5f575f80fd5b6200061e8262000798565b634e487b7160e01b5f52603260045260245ffd5b5f6020828403121562000a8f575f80fd5b815180151581146200061e575f80fd5b80820180821115620006d857634e487b7160e01b5f52601160045260245ffd5b5f825162000ad2818460208701620007fb565b9190910192915050565b60805160a05160c05160e0516101005161012051610140516101605161513062000bfc5f395f8181611f060152613dda01525f8181611397015261182f01525f8181610f0d015281816115ae01528181611d09015281816123cd015281816125ed015261280201525f61033f01525f818161030c015281816107e50152611c8101525f818161048401526138ea01525f81816109a001528181610aa001528181610f9701526111b801525f818161085a015281816117230152818161185b01528181611947015281816119c501528181611ac901528181611f2901528181612470015281816124bd015281816129eb01528181612a9101528181612fec015281816132490152818161364e0152818161388f0152613fec01526151305ff3fe6080604052600436106101e2575f3560e01c80638a4adf2411610101578063c7b9d53011610094578063d65ba11a11610063578063d65ba11a14610671578063ecf7085814610686578063f23a6e611461069b578063fde813a8146104f0576101e2565b8063c7b9d530146105d2578063ca70baa3146105f1578063d01f63f514610629578063d19a3bb81461064a576101e2565b8063b5f163ff116100d0578063b5f163ff1461052e578063bc197c811461054d578063bdc8144b14610594578063c04dad5d146105b3576101e2565b80638a4adf24146104be5780638adb2ca9146104dd5780639d7fb70c146104f0578063b543503e1461050f576101e2565b80633d6cb575116101795780635d265d3f116101485780635d265d3f146103f457806377ca76b81461043557806381cd63771461045457806385e1f4d014610473576101e2565b80633d6cb5751461038357806346aa2f12146103a257806349317f1d146103c1578063503160d9146103d5576101e2565b80631fe4a686116101b55780631fe4a686146102c557806324c73dda146102fb57806334c041a51461032e57806335ad30b514610361576101e2565b806301ffc9a71461022357806304bd46291461025757806310bc7abf1461028557806318354273146102b1575b3480156101ed575f80fd5b5073bb51273d6c746910c7c06fe718f30c936170fed0365f80375f80365f845af43d5f803e80801561021d573d5ff35b3d5ffd5b005b34801561022e575f80fd5b5061024261023d3660046145a0565b6106c7565b60405190151581526020015b60405180910390f35b348015610262575f80fd5b506102776102713660046145db565b505f1990565b60405190815260200161024e565b348015610290575f80fd5b506102a461029f3660046146c8565b6106fd565b60405161024e91906146f9565b3480156102bc575f80fd5b506102216107ae565b3480156102d0575f80fd5b505f546102e3906001600160a01b031681565b6040516001600160a01b03909116815260200161024e565b348015610306575f80fd5b506102e37f000000000000000000000000000000000000000000000000000000000000000081565b348015610339575f80fd5b506102e37f000000000000000000000000000000000000000000000000000000000000000081565b34801561036c575f80fd5b506103756108d9565b60405161024e929190614778565b34801561038e575f80fd5b5061022161039d36600461479c565b610988565b3480156103ad575f80fd5b506102776103bc3660046145db565b61099c565b3480156103cc575f80fd5b50610277610a45565b3480156103e0575f80fd5b506102216103ef36600461479c565b610a5b565b3480156103ff575f80fd5b5060408051600481526024810182526020810180516001600160e01b031663440368a360e01b179052905161024e915f91614800565b348015610440575f80fd5b5061027761044f36600461479c565b610a6c565b34801561045f575f80fd5b5061022161046e36600461481a565b610a8b565b34801561047e575f80fd5b506104a67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160401b03909116815260200161024e565b3480156104c9575f80fd5b506001546102e3906001600160a01b031681565b6102216104eb36600461483d565b610b4a565b3480156104fb575f80fd5b5061022161050a36600461479c565b610f7a565b34801561051a575f80fd5b506102216105293660046145db565b610f82565b348015610539575f80fd5b5061027761054836600461479c565b611072565b348015610558575f80fd5b5061057b6105673660046148f7565b63bc197c8160e01b98975050505050505050565b6040516001600160e01b0319909116815260200161024e565b34801561059f575f80fd5b506102216105ae36600461479c565b611081565b3480156105be575f80fd5b506102216105cd3660046149ba565b6110e1565b3480156105dd575f80fd5b506102216105ec3660046145db565b6111a3565b3480156105fc575f80fd5b5060015461061490600160a01b900463ffffffff1681565b60405163ffffffff909116815260200161024e565b348015610634575f80fd5b5061063d611264565b60405161024e9190614a77565b348015610655575f80fd5b506102e373bb51273d6c746910c7c06fe718f30c936170fed081565b34801561067c575f80fd5b5061027760025481565b348015610691575f80fd5b5061027760035481565b3480156106a6575f80fd5b5061057b6106b5366004614a89565b63f23a6e6160e01b9695505050505050565b5f6001600160e01b031982166301ffc9a760e01b14806106f757506001600160e01b03198216630271189760e51b145b92915050565b8051606090806001600160401b0381111561071a5761071a6145f6565b604051908082528060200260200182016040528015610743578160200160208202803683370190505b5091505f5b818110156107a75761077d84828151811061076557610765614aff565b6020026020010151600461127090919063ffffffff16565b83828151811061078f5761078f614aff565b91151560209283029190910190910152600101610748565b5050919050565b6040516321f8a72160e01b81527fbddfa8c39a1f6275bcfb3aa5c70638c466999edbf14e6162d81b3492caca9fce60048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa158015610832573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108569190614b13565b90507f00000000000000000000000000000000000000000000000000000000000000005f6108838261128a565b905080156108d45761089f6001600160a01b03831684836112f2565b6040518181527f76a820ad5e56aebcfa13f60a4ec2e8453550cca0e77446a259782e547c68b32b906020015b60405180910390a15b505050565b606080600660078180548060200260200160405190810160405280929190818152602001828054801561092957602002820191905f5260205f20905b815481526020019060010190808311610915575b505050505091508080548060200260200160405190810160405280929190818152602001828054801561097957602002820191905f5260205f20905b815481526020019060010190808311610965575b50505050509050915091509091565b610990611351565b6109998161138f565b50565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301e1d1146040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109fa573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a1e9190614b2e565b60035490915080821015610a3b57610a368282614b59565b610a3d565b5f5b949350505050565b5f610a4e611351565b610a56611555565b905090565b610a63611351565b6109998161175a565b60068181548110610a7b575f80fd5b5f91825260209091200154905081565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a649906024015f6040518083038186803b158015610ae8575f80fd5b505afa158015610afa573d5f803e3d5ffd5b505050508063ffffffff165f03610b24576040516360d4aee560e11b815260040160405180910390fd5b6001805463ffffffff909216600160a01b0263ffffffff60a01b19909216919091179055565b5f546001600160a01b03163314610b74576040516312b9d85760e01b815260040160405180910390fd5b5f610b7f8280614b6c565b91505f9050610b916020840184614b6c565b91505f9050610ba36040850185614b6c565b90509050815f03610bc75760405163ec5e1a0b60e01b815260040160405180910390fd5b805f03610be757604051636e1d500960e11b815260040160405180910390fd5b8183141580610c045750610bfe6060850185614b6c565b90508114155b15610c2257604051634456f5e960e11b815260040160405180910390fd5b6002545f90815b85811015610ca2575f5b82811015610c995760068181548110610c4e57610c4e614aff565b5f91825260209091200154610c638980614b6c565b84818110610c7357610c73614aff565b9050602002013503610c915783610c8981614bb1565b945050610c99565b600101610c33565b50600101610c29565b50848214610cc35760405163173b81c360e21b815260040160405180910390fd5b50600190505b83811015610d4657610cdb8580614b6c565b610ce6600184614b59565b818110610cf557610cf5614aff565b60200291909101359050610d098680614b6c565b83818110610d1957610d19614aff565b9050602002013511610d3e5760405163ac5c256f60e01b815260040160405180910390fd5b600101610cc9565b505f5b81811015610e2f5760018110158015610db55750610d6a6040860186614b6c565b610d75600184614b59565b818110610d8457610d84614aff565b90506020020135858060400190610d9b9190614b6c565b83818110610dab57610dab614aff565b9050602002013511155b15610dd3576040516345109f5760e11b815260040160405180910390fd5b610e0a610de36040870187614b6c565b83818110610df357610df3614aff565b90506020020135600461127090919063ffffffff16565b610e275760405163d902535160e01b815260040160405180910390fd5b600101610d49565b505f610e6f610e3e8680614b6c565b610e4b6020890189614b6c565b610e5860408b018b614b6c565b610e6560608d018d614b6c565b8d608001356119f3565b90505f610e9b7fcfa3537c7b7ad87a0dd290c1d493cb256cbf491441572cd66c66c6af6310399b611c69565b9050610eaf81835f01518460200151611cf2565b604051633452c8ed60e21b81526001600160a01b0382169063d14b23b490610edb908590600401614bc9565b5f604051808303815f87803b158015610ef2575f80fd5b505af1158015610f04573d5f803e3d5ffd5b50505050610f727f0000000000000000000000000000000000000000000000000000000000000000878060400190610f3c9190614b6c565b808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250611d7492505050565b505050505050565b610999611351565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a649906024015f6040518083038186803b158015610fdf575f80fd5b505afa158015610ff1573d5f803e3d5ffd5b5050506001600160a01b038216905061101d5760405163538ba4f960e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f8e902340d35762a5a36507c20fe38e5d549a721d9f846d6de7f397b5c26ab853906020015b60405180910390a150565b60078181548110610a7b575f80fd5b6001546001600160a01b031633146110ac57604051634f9aa11760e11b815260040160405180910390fd5b60038190556040518181527f5d2e73196f8ba1b44e887e2bcc9bcd1f3e657add341d4a0a632ffff00d6903f290602001611067565b6001546001600160a01b0316331461110c57604051634f9aa11760e11b815260040160405180910390fd5b81518151811461112f57604051634456f5e960e11b815260040160405180910390fd5b805f0361114f576040516342c313c360e11b815260040160405180910390fd5b5f5b8181101561119d5761119584828151811061116e5761116e614aff565b602002602001015184838151811061118857611188614aff565b60200260200101516122b8565b600101611151565b50505050565b6040516348e4a64960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a649906024015f6040518083038186803b158015611200575f80fd5b505afa158015611212573d5f803e3d5ffd5b50505f80546001600160a01b0319166001600160a01b0385169081179091556040519081527f276625620b877c2ddc0a05d68b81971639085fa26d23dfa86eec6460e6fac5b992506020019050611067565b6060610a566004612325565b5f81815260018301602052604081205415155b9392505050565b6040516370a0823160e01b81523060048201525f906001600160a01b038316906370a0823190602401602060405180830381865afa1580156112ce573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f79190614b2e565b6040516001600160a01b038381166024830152604482018390526108d491859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050612331565b33301461138d5760405162461bcd60e51b815260206004820152600560248201526410b9b2b63360d91b60448201526064015b60405180910390fd5b565b6002546060907f00000000000000000000000000000000000000000000000000000000000000009060010361143d575f6113c884612392565b60408051602081018252828152905191925063407c7b1d60e01b916113f09190602401614d0e565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050925061143782825f015183602001516125c0565b506114b8565b5f6114478461261c565b604080516020810182528281529051919250630b0702e960e21b9161146f9190602401614e81565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b03838183161783525050505092506114b682825f01518360200151611cf2565b505b5f80826001600160a01b0316846040516114d29190614f98565b5f604051808303815f865af19150503d805f811461150b576040519150601f19603f3d011682016040523d82523d5f602084013e611510565b606091505b5091509150610f7282826040518060400160405280601a81526020017f43616c6c526576657274576974684e6f52657475726e44617461000000000000815250612d0f565b60025460068054604080516020808402820181019092528281525f948594909385938301828280156115a457602002820191905f5260205f20905b815481526020019060010190808311611590575b505050505090505f7f000000000000000000000000000000000000000000000000000000000000000090505f5b8381101561171d575f6115fc8483815181106115ef576115ef614aff565b6020026020010151612d28565b505090505f836001600160a01b031662fdd58e3087868151811061162257611622614aff565b60200260200101516040518363ffffffff1660e01b815260040161165b9291906001600160a01b03929092168252602082015260400190565b602060405180830381865afa158015611676573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061169a9190614b2e565b60405163b7ba28cd60e01b8152600481018290529091506001600160a01b0383169063b7ba28cd90602401602060405180830381865afa1580156116e0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117049190614b2e565b61170e9088614fb3565b965082600101925050506115d1565b506117477f000000000000000000000000000000000000000000000000000000000000000061128a565b6117519085614fb3565b94505050505090565b5f6002546001146117ca5763fa0f64eb60e01b604051806020016040528061178185612d5b565b90526040516117939190602401614e81565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261182b565b63b19dcc3360e01b60405180602001604052806117e685613203565b90526040516117f89190602401614d0e565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091525b90507f00000000000000000000000000000000000000000000000000000000000000006118826001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168285613375565b5f80826001600160a01b03168460405161189c9190614f98565b5f604051808303815f865af19150503d805f81146118d5576040519150601f19603f3d011682016040523d82523d5f602084013e6118da565b606091505b509150915061191f82826040518060400160405280601a81526020017f43616c6c526576657274576974684e6f52657475726e44617461000000000000815250612d0f565b50604051636eb1769f60e11b81523060048201526001600160a01b0384811660248301525f917f00000000000000000000000000000000000000000000000000000000000000009091169063dd62ed3e90604401602060405180830381865afa15801561198e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119b29190614b2e565b11156119ec576119ec6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016845f6133f7565b5050505050565b611a5560405180610140016040528060608152602001606081526020015f81526020015f81526020015f81526020015f6001600160a01b031681526020015f81526020015f6001600160a01b0316815260200160608152602001606081525090565b8989808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250505090825250604080516020808a02828101820190935289825290918a918a9182918501908490808284375f9201829052506020808701959095526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660a087015260c086018790523060e0870152604080518f870281810188019092528f81529195869550611b8094509192508f918f9182918501908490808284375f81840152601f19601f820116905080830192505050505050508b8b808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250899250600191506134869050565b91509150632c1c0ba460e01b82604051602401611b9d9190614e81565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526101008401525f80611be38a8a8a8a6139e9565b91509150611bfc82611bf58584613bbb565b885f613486565b5060405190945063fa0f64eb60e01b90611c1a908690602401614e81565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925261012087015285019290925250919b9a5050505050505050505050565b6040516321f8a72160e01b8152600481018290525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa158015611cce573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f79190614b13565b6040516317ea35d960e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635fa8d76490611d4290869086908690600401614fc6565b5f604051808303815f87803b158015611d59575f80fd5b505af1158015611d6b573d5f803e3d5ffd5b50505050505050565b5f6006805480602002602001604051908101604052809291908181526020018280548015611dbf57602002820191905f5260205f20905b815481526020019060010190808311611dab575b5050835186519495509392505f9150505b82811015611e9a575f805b83811015611e2d57868181518110611df557611df5614aff565b6020026020010151868481518110611e0f57611e0f614aff565b602002602001015103611e255760019150611e2d565b600101611ddb565b5080611e9157611e5687868481518110611e4957611e49614aff565b6020026020010151613c6b565b15611e9157848281518110611e6d57611e6d614aff565b602002602001015160405163350085c960e11b815260040161138491815260200190565b50600101611dd0565b5083515f90808203611ebf576040516342c313c360e11b815260040160405180910390fd5b5f816001600160401b03811115611ed857611ed86145f6565b604051908082528060200260200182016040528015611f01578160200160208202803683370190505b5090507f00000000000000000000000000000000000000000000000000000000000000005f807f0000000000000000000000000000000000000000000000000000000000000000815b8681101561217557846001600160a01b031663b5c756978d8381518110611f7357611f73614aff565b60200260200101516040518263ffffffff1660e01b8152600401611f9991815260200190565b602060405180830381865afa158015611fb4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fd89190614ffb565b612012578b8181518110611fee57611fee614aff565b60200260200101516040516317ed28b560e31b815260040161138491815260200190565b6120278c82815181106115ef576115ef614aff565b90505080945050816001600160a01b0316846001600160a01b031663b60262ca6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612074573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120989190614b13565b6001600160a01b0316146120bf576040516307397cd760e01b815260040160405180910390fd5b5f6120d68e8e8481518110611e4957611e49614aff565b60405163b7ba28cd60e01b8152600481018290529091506001600160a01b0386169063b7ba28cd90602401602060405180830381865afa15801561211c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121409190614b2e565b93508387838151811061215557612155614aff565b602090810291909101015261216a848a614fb3565b985050600101611f4a565b505f805b612184600189614b59565b81101561220a576121bd6127108a5f8a85815181106121a5576121a5614aff565b6020026020010151613cd8909392919063ffffffff16565b8782815181106121cf576121cf614aff565b6020026020010181815250508681815181106121ed576121ed614aff565b6020026020010151826122009190614fb3565b9150600101612179565b5061221781612710614b59565b8661222360018a614b59565b8151811061223357612233614aff565b6020026020010181815250508560079080519060200190612255929190614433565b508b516122699060069060208f0190614433565b5060028790556040517fb60570021257b8c021f071d6b761bf920e130dbbd2c819989f690f8337253b88906122a1908e908990614778565b60405180910390a150505050505050505050505050565b5f6122c4600484611270565b9050811515811515146108d45781156122e5576122e083613d33565b6122ee565b6122ee83613d42565b6040805184815283151560208201527ff5b8e2d9dfe40944d8ee0c9b9039acd8516760f92d19ef0f6aba3e0994d7287691016108cb565b60605f61128383613d4d565b5f6123456001600160a01b03841683613da6565b905080515f141580156123695750808060200190518101906123679190614ffb565b155b156108d457604051635274afe760e01b81526001600160a01b0384166004820152602401611384565b61239a61447c565b60065f815481106123ad576123ad614aff565b5f9182526020822001548083526123c390612d28565b505090505f6123f57f0000000000000000000000000000000000000000000000000000000000000000845f0151613c6b565b60405163b7ba28cd60e01b8152600481018290529091505f906001600160a01b0384169063b7ba28cd90602401602060405180830381865afa15801561243d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124619190614b2e565b60808501516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660209091015284519091505f906124a690613db3565b905080156124e45760808501516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166040909101525b81861061250657602085018390526124fc8183613f79565b6040860152612594565b6125108187613f79565b604086810191909152516307c080f960e01b8152600481018790526001600160a01b038516906307c080f990602401602060405180830381865afa15801561255a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061257e9190614b2e565b6020860181905283101561259457602085018390525b50506064606084015250505f60c0820181905260e0820152306101008201819052610120820152919050565b60405163524fca8b60e11b81526001600160a01b03848116600483015260248201849052604482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a49f951690606401611d42565b6126246144d6565b600254600680546040805160208084028201810190925282815292919083018282801561266e57602002820191905f5260205f20905b81548152602001906001019080831161265a575b505050918452508190506001600160401b0381111561268f5761268f6145f6565b6040519080825280602002602001820160405280156126b8578160200160208202803683370190505b506020830152806001600160401b038111156126d6576126d66145f6565b6040519080825280602002602001820160405280156126ff578160200160208202803683370190505b506060830152806001600160401b0381111561271d5761271d6145f6565b60405190808252806020026020018201604052801561275657816020015b612743614540565b81526020019060019003908161273b5790505b506080830152806001600160401b03811115612774576127746145f6565b60405190808252806020026020018201604052801561279d578160200160208202803683370190505b5060c0830181905260e0830152306101008301819052610120830152806001600160401b038111156127d1576127d16145f6565b6040519080825280602002602001820160405280156127fa578160200160208202803683370190505b5060408301527f00000000000000000000000000000000000000000000000000000000000000005f80836001600160401b0381111561283b5761283b6145f6565b604051908082528060200260200182016040528015612864578160200160208202803683370190505b5090505f846001600160401b03811115612880576128806145f6565b6040519080825280602002602001820160405280156128a9578160200160208202803683370190505b5090505f5b858110156129de575f6128cf885f015183815181106115ef576115ef614aff565b505090506128ec86895f01518481518110611e4957611e49614aff565b8483815181106128fe576128fe614aff565b602002602001018181525050806001600160a01b031663b7ba28cd85848151811061292b5761292b614aff565b60200260200101516040518263ffffffff1660e01b815260040161295191815260200190565b602060405180830381865afa15801561296c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129909190614b2e565b8383815181106129a2576129a2614aff565b6020026020010181815250508282815181106129c0576129c0614aff565b6020026020010151856129d39190614fb3565b9450506001016128ae565b505f5b85811015612d04577f000000000000000000000000000000000000000000000000000000000000000087608001518281518110612a2057612a20614aff565b6020026020010151602001906001600160a01b031690816001600160a01b0316815250505f612a5d885f015183815181106115ef576115ef614aff565b505090505f612a87895f01518481518110612a7a57612a7a614aff565b6020026020010151613db3565b90508015612aeb577f000000000000000000000000000000000000000000000000000000000000000089608001518481518110612ac657612ac6614aff565b6020026020010151604001906001600160a01b031690816001600160a01b0316815250505b858a10612b7857848381518110612b0457612b04614aff565b602002602001015189602001518481518110612b2257612b22614aff565b602002602001018181525050612b5181858581518110612b4457612b44614aff565b6020026020010151613f79565b89604001518481518110612b6757612b67614aff565b602002602001018181525050612cd7565b5f612ba460078581548110612b8f57612b8f614aff565b5f9182526020822001548d9161271090613cd8565b9050612bb08282613f79565b8a604001518581518110612bc657612bc6614aff565b60209081029190910101526040516307c080f960e01b8152600481018290526001600160a01b038416906307c080f990602401602060405180830381865afa158015612c14573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c389190614b2e565b8a602001518581518110612c4e57612c4e614aff565b602002602001018181525050858481518110612c6c57612c6c614aff565b60200260200101518a602001518581518110612c8a57612c8a614aff565b60200260200101511115612cd557858481518110612caa57612caa614aff565b60200260200101518a602001518581518110612cc857612cc8614aff565b6020026020010181815250505b505b606489606001518481518110612cef57612cef614aff565b602090810291909101015250506001016129e1565b505050505050919050565b60608315612d1e575081611283565b6112838383613f90565b8060a081901c60c082901c5f819003612d545760405163030042b760e01b815260040160405180910390fd5b9193909250565b612d636144d6565b6002546006805460408051602080840282018101909252828152929190830182828015612dad57602002820191905f5260205f20905b815481526020019060010190808311612d99575b505050918452508190506001600160401b03811115612dce57612dce6145f6565b604051908082528060200260200182016040528015612df7578160200160208202803683370190505b506020830152806001600160401b03811115612e1557612e156145f6565b604051908082528060200260200182016040528015612e3e578160200160208202803683370190505b506060830152806001600160401b03811115612e5c57612e5c6145f6565b604051908082528060200260200182016040528015612e9557816020015b612e82614540565b815260200190600190039081612e7a5790505b506080830152806001600160401b03811115612eb357612eb36145f6565b604051908082528060200260200182016040528015612edc578160200160208202803683370190505b5060c0830181905260e0830152306101008301819052610120830152806001600160401b03811115612f1057612f106145f6565b604051908082528060200260200182016040528015612f39578160200160208202803683370190505b5060408301525f816001600160401b03811115612f5857612f586145f6565b604051908082528060200260200182016040528015612f8b57816020015b6060815260200190600190039081612f765790505b5090505f6007805480602002602001604051908101604052809291908181526020018280548015612fd957602002820191905f5260205f20905b815481526020019060010190808311612fc5575b505050505090505f5b838110156131d0577f00000000000000000000000000000000000000000000000000000000000000008560800151828151811061302157613021614aff565b6020026020010151602001906001600160a01b031690816001600160a01b0316815250505f61305e865f015183815181106115ef576115ef614aff565b50509050613087865f0151838151811061307a5761307a614aff565b6020026020010151613fba565b84838151811061309957613099614aff565b60200260200101819052506130d68383815181106130b9576130b9614aff565b60200260200101516127105f8a613cd8909392919063ffffffff16565b866020015183815181106130ec576130ec614aff565b602002602001018181525050806001600160a01b03166307c080f98760200151848151811061311d5761311d614aff565b60200260200101516040518263ffffffff1660e01b815260040161314391815260200190565b602060405180830381865afa15801561315e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131829190614b2e565b8660400151838151811061319857613198614aff565b6020026020010181815250506064866060015183815181106131bc576131bc614aff565b602090810291909101015250600101612fe2565b5082826040516020016131e4929190615061565b60408051601f1981840301815291905261014085015250919392505050565b61320b61447c565b60065f8154811061321e5761321e614aff565b5f91825260208083209091015483528281018490526064606084015260808301516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691015260c0820181905260e08201819052306101008301819052610120830152815161329490612d28565b50506040516307c080f960e01b8152600481018590529091506001600160a01b038216906307c080f990602401602060405180830381865afa1580156132dc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906133009190614b2e565b604083015281515f9061331290613fba565b6040805160018082528183019092529192505f9190816020015b606081526020019060019003908161332c57905050905081815f8151811061335657613356614aff565b60200260200101819052506001816040516020016131e4929190615079565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301525f919085169063dd62ed3e90604401602060405180830381865afa1580156133c2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906133e69190614b2e565b905061119d84846133f78585614fb3565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052613448848261404e565b61119d576040516001600160a01b0384811660248301525f604483015261347c91869182169063095ea7b39060640161131f565b61119d8482612331565b61348e614574565b5f6134976144d6565b868152602081018690525f6134cb7fcfa3537c7b7ad87a0dd290c1d493cb256cbf491441572cd66c66c6af6310399b611c69565b8851909150806001600160401b038111156134e8576134e86145f6565b604051908082528060200260200182016040528015613511578160200160208202803683370190505b506040840152806001600160401b0381111561352f5761352f6145f6565b604051908082528060200260200182016040528015613558578160200160208202803683370190505b506060840152806001600160401b03811115613576576135766145f6565b6040519080825280602002602001820160405280156135af57816020015b61359c614540565b8152602001906001900390816135945790505b5060808401525f816001600160401b038111156135ce576135ce6145f6565b60405190808252806020026020018201604052801561360157816020015b60608152602001906001900390816135ec5790505b5090505f5b82811015613944575f6136248c83815181106115ef576115ef614aff565b505090508815613764575f6136448d8481518110612a7a57612a7a614aff565b905080156136a8577f00000000000000000000000000000000000000000000000000000000000000008760800151848151811061368357613683614aff565b6020026020010151604001906001600160a01b031690816001600160a01b0316815250505b5f826001600160a01b031663b7ba28cd8e86815181106136ca576136ca614aff565b60200260200101516040518263ffffffff1660e01b81526004016136f091815260200190565b602060405180830381865afa15801561370b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061372f9190614b2e565b905061373b8282613f79565b8860400151858151811061375157613751614aff565b602002602001018181525050505061383f565b6137798c838151811061307a5761307a614aff565b83838151811061378b5761378b614aff565b6020026020010181905250806001600160a01b03166307c080f98c84815181106137b7576137b7614aff565b60200260200101516040518263ffffffff1660e01b81526004016137dd91815260200190565b602060405180830381865afa1580156137f8573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061381c9190614b2e565b8660400151838151811061383257613832614aff565b6020026020010181815250505b8560400151828151811061385557613855614aff565b6020026020010151876138689190614fb3565b9650898660600151838151811061388157613881614aff565b6020026020010181815250507f0000000000000000000000000000000000000000000000000000000000000000866080015183815181106138c4576138c4614aff565b6020026020010151602001906001600160a01b031690816001600160a01b0316815250507f00000000000000000000000000000000000000000000000000000000000000008660800151838151811061391f5761391f614aff565b60209081029190910101516001600160401b0390911660809091015250600101613606565b50816001600160401b0381111561395d5761395d6145f6565b604051908082528060200260200182016040528015613986578160200160208202803683370190505b5060c0850181905260e08501526001600160a01b03831661010085015230610120850152866139d95781816040516020016139c2929190615061565b60408051601f198184030181529190526101408501525b5050508252909590945092505050565b6060805f83815b81811015613a2d57868682818110613a0a57613a0a614aff565b905060200201355f14613a255782613a2181614bb1565b9350505b6001016139f0565b50816001600160401b03811115613a4657613a466145f6565b604051908082528060200260200182016040528015613a6f578160200160208202803683370190505b509350816001600160401b03811115613a8a57613a8a6145f6565b604051908082528060200260200182016040528015613ab3578160200160208202803683370190505b5092505f805f5b83811015613b8b57888882818110613ad457613ad4614aff565b905060200201355f14613b83578a8a82818110613af357613af3614aff565b90506020020135878481518110613b0c57613b0c614aff565b602002602001018181525050888882818110613b2a57613b2a614aff565b90506020020135868481518110613b4357613b43614aff565b602002602001018181525050888882818110613b6157613b61614aff565b9050602002013582613b739190614fb3565b915082613b7f81614bb1565b9350505b600101613aba565b506127108114613bae576040516314ccf61760e31b815260040160405180910390fd5b5050505094509492505050565b606081516001600160401b03811115613bd657613bd66145f6565b604051908082528060200260200182016040528015613bff578160200160208202803683370190505b5090505f5b8251811015613c6457613c3f838281518110613c2257613c22614aff565b60200260200101516127105f87613cd8909392919063ffffffff16565b828281518110613c5157613c51614aff565b6020908102919091010152600101613c04565b5092915050565b604051627eeac760e11b8152306004820152602481018290525f906001600160a01b0384169062fdd58e90604401602060405180830381865afa158015613cb4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112839190614b2e565b5f80613ce58686866140eb565b90506001836002811115613cfb57613cfb615094565b148015613d1757505f8480613d1257613d126150a8565b868809115b15613d2a57613d27600182614fb3565b90505b95945050505050565b613d3e6004826141d0565b5050565b613d3e6004826141db565b6060815f01805480602002602001604051908101604052809291908181526020018280548015613d9a57602002820191905f5260205f20905b815481526020019060010190808311613d86575b50505050509050919050565b606061128383835f6141e6565b600154604051632ece023360e21b8152600160a01b90910463ffffffff1660048201525f907f00000000000000000000000000000000000000000000000000000000000000009082906001600160a01b0383169063bb3808cc90602401602060405180830381865afa158015613e2b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613e4f9190614b13565b90505f613e5b85612d28565b505090505f836001600160a01b031663b85225bb84846001600160a01b03166365cacaa46040518163ffffffff1660e01b8152600401602060405180830381865afa158015613eac573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613ed09190614b13565b604080516001600160a01b0393841660208201529290911690820152606001604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401613f2391815260200190565b602060405180830381865afa158015613f3e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613f629190614b2e565b9050858103613f7057600194505b50505050919050565b5f82613f855781611283565b611283600a83614b59565b815115613fa05781518083602001fd5b8060405162461bcd60e51b815260040161138491906150bc565b60605f613fc683613db3565b613fde5760405180602001604052805f815250614022565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166020820152016040516020818303038152906040525b905082816040516020016140379291906150ce565b604051602081830303815290604052915050919050565b5f805f846001600160a01b0316846040516140699190614f98565b5f604051808303815f865af19150503d805f81146140a2576040519150601f19603f3d011682016040523d82523d5f602084013e6140a7565b606091505b50915091508180156140d15750805115806140d15750808060200190518101906140d19190614ffb565b8015613d2a5750505050506001600160a01b03163b151590565b5f80805f19858709858702925082811083820303915050805f0361412257838281614118576141186150a8565b0492505050611283565b8084116141695760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b6044820152606401611384565b5f8486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091025f889003889004909101858311909403939093029303949094049190911702949350505050565b5f611283838361427f565b5f61128383836142cb565b60608147101561420b5760405163cd78605960e01b8152306004820152602401611384565b5f80856001600160a01b031684866040516142269190614f98565b5f6040518083038185875af1925050503d805f8114614260576040519150601f19603f3d011682016040523d82523d5f602084013e614265565b606091505b50915091506142758683836143ae565b9695505050505050565b5f8181526001830160205260408120546142c457508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556106f7565b505f6106f7565b5f81815260018301602052604081205480156143a5575f6142ed600183614b59565b85549091505f9061430090600190614b59565b905081811461435f575f865f01828154811061431e5761431e614aff565b905f5260205f200154905080875f01848154811061433e5761433e614aff565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080614370576143706150e6565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506106f7565b5f9150506106f7565b6060826143c3576143be8261440a565b611283565b81511580156143da57506001600160a01b0384163b155b1561440357604051639996b31560e01b81526001600160a01b0385166004820152602401611384565b5080611283565b80511561441a5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b828054828255905f5260205f2090810192821561446c579160200282015b8281111561446c578251825591602001919060010190614451565b5061447892915061458c565b5090565b6040518061016001604052805f81526020015f81526020015f81526020015f81526020016144a8614540565b81526060602082018190525f604083018190528183018190526080830181905260a083015260c09091015290565b60405180610160016040528060608152602001606081526020016060815260200160608152602001606081526020016060815260200160608152602001606081526020015f6001600160a01b031681526020015f6001600160a01b03168152602001606081525090565b6040805160c08101825260608082525f6020830181905292820183905281018290526080810182905260a081019190915290565b60405180602001604052806145876144d6565b905290565b5b80821115614478575f815560010161458d565b5f602082840312156145b0575f80fd5b81356001600160e01b031981168114611283575f80fd5b6001600160a01b0381168114610999575f80fd5b5f602082840312156145eb575f80fd5b8135611283816145c7565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715614632576146326145f6565b604052919050565b5f6001600160401b03821115614652576146526145f6565b5060051b60200190565b5f82601f83011261466b575f80fd5b8135602061468061467b8361463a565b61460a565b8083825260208201915060208460051b8701019350868411156146a1575f80fd5b602086015b848110156146bd57803583529183019183016146a6565b509695505050505050565b5f602082840312156146d8575f80fd5b81356001600160401b038111156146ed575f80fd5b610a3d8482850161465c565b602080825282518282018190525f9190848201906040850190845b81811015614732578351151583529284019291840191600101614714565b50909695505050505050565b5f815180845260208085019450602084015f5b8381101561476d57815187529582019590820190600101614751565b509495945050505050565b604081525f61478a604083018561473e565b8281036020840152613d2a818561473e565b5f602082840312156147ac575f80fd5b5035919050565b5f5b838110156147cd5781810151838201526020016147b5565b50505f910152565b5f81518084526147ec8160208601602086016147b3565b601f01601f19169290920160200192915050565b8215158152604060208201525f610a3d60408301846147d5565b5f6020828403121561482a575f80fd5b813563ffffffff81168114611283575f80fd5b5f6020828403121561484d575f80fd5b81356001600160401b03811115614862575f80fd5b820160a08185031215611283575f80fd5b5f8083601f840112614883575f80fd5b5081356001600160401b03811115614899575f80fd5b6020830191508360208260051b85010111156148b3575f80fd5b9250929050565b5f8083601f8401126148ca575f80fd5b5081356001600160401b038111156148e0575f80fd5b6020830191508360208285010111156148b3575f80fd5b5f805f805f805f8060a0898b03121561490e575f80fd5b8835614919816145c7565b97506020890135614929816145c7565b965060408901356001600160401b0380821115614944575f80fd5b6149508c838d01614873565b909850965060608b0135915080821115614968575f80fd5b6149748c838d01614873565b909650945060808b013591508082111561498c575f80fd5b506149998b828c016148ba565b999c989b5096995094979396929594505050565b8015158114610999575f80fd5b5f80604083850312156149cb575f80fd5b82356001600160401b03808211156149e1575f80fd5b6149ed8683870161465c565b9350602091508185013581811115614a03575f80fd5b85019050601f81018613614a15575f80fd5b8035614a2361467b8261463a565b81815260059190911b82018301908381019088831115614a41575f80fd5b928401925b82841015614a68578335614a59816149ad565b82529284019290840190614a46565b80955050505050509250929050565b602081525f611283602083018461473e565b5f805f805f8060a08789031215614a9e575f80fd5b8635614aa9816145c7565b95506020870135614ab9816145c7565b9450604087013593506060870135925060808701356001600160401b03811115614ae1575f80fd5b614aed89828a016148ba565b979a9699509497509295939492505050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215614b23575f80fd5b8151611283816145c7565b5f60208284031215614b3e575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106f7576106f7614b45565b5f808335601e19843603018112614b81575f80fd5b8301803591506001600160401b03821115614b9a575f80fd5b6020019150600581901b36038213156148b3575f80fd5b5f60018201614bc257614bc2614b45565b5060010190565b602081525f8251610140806020850152614be761016085018361473e565b91506020850151601f1980868503016040870152614c05848361473e565b93506040870151606087015260608701516080870152608087015160a087015260a08701519150614c4160c08701836001600160a01b03169052565b60c087015160e087015260e08701519150610100614c69818801846001600160a01b03169052565b80880151925050610120818786030181880152614c8685846147d5565b90880151878203909201848801529350905061427583826147d5565b5f815160c08452614cb660c08501826147d5565b9050602083015160018060a01b038082166020870152806040860151166040870152505060ff60608401511660608501526001600160401b03608084015116608085015260a083015160a08501528091505092915050565b602081525f8251602080840152805160408401526020810151606084015260408101516080840152606081015160a084015260808101516101608060c0860152614d5c6101a0860183614ca2565b915060a0830151603f19808785030160e0880152614d7a84836147d5565b935060c08501519150610100614d938189018415159052565b60e08601519250610120614daa818a018515159052565b90860151925061014090614dc8898301856001600160a01b03169052565b8601516001600160a01b03169388019390935291909301518583039091016101808601529150613d2a81836147d5565b5f8282518085526020808601955060208260051b840101602086015f5b84811015614e4357601f19868403018952614e31838351614ca2565b98840198925090830190600101614e15565b5090979650505050505050565b5f815180845260208085019450602084015f5b8381101561476d578151151587529582019590820190600101614e63565b602081525f82516020808401528051610160806040860152614ea76101a086018361473e565b91506020830151603f1980878503016060880152614ec5848361473e565b93506040850151915080878503016080880152614ee2848361473e565b935060608501519150808785030160a0880152614eff848361473e565b935060808501519150808785030160c0880152614f1c8483614df8565b935060a08501519150808785030160e0880152614f3984836147d5565b935060c08501519150610100818886030181890152614f588584614e50565b945060e086015192506101208289870301818a0152614f778685614e50565b95508187015193506101409150614dc8828a01856001600160a01b03169052565b5f8251614fa98184602087016147b3565b9190910192915050565b808201808211156106f7576106f7614b45565b6001600160a01b03841681526060602082018190525f90614fe99083018561473e565b8281036040840152614275818561473e565b5f6020828403121561500b575f80fd5b8151611283816149ad565b5f8282518085526020808601955060208260051b840101602086015f5b84811015614e4357601f1986840301895261504f8383516147d5565b98840198925090830190600101615033565b828152604060208201525f610a3d6040830184615016565b60ff83168152604060208201525f610a3d6040830184615016565b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52601260045260245ffd5b602081525f61128360208301846147d5565b828152604060208201525f610a3d60408301846147d5565b634e487b7160e01b5f52603160045260245ffdfea264697066735822122084dc9ef8254b7f2d70223b44c21428352171c4b4b68adb9e9c7c089f7146953b64736f6c6343000818003300000000000000000000000017a332dc7b40ae701485023b219e9d6f493a2514000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000fa476c5ec7a43a68e081fd5a33f668f0bd09e126000000000000000000000000701ae9c540ba2144b669f22e650882e7e07cb11f0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000e8d4a5100000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000953757065725553444300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000100000001473b1ce36dec21fc1275c4032731c8469bff371a00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000002710
Deployed Bytecode
0x6080604052600436106101e2575f3560e01c80638a4adf2411610101578063c7b9d53011610094578063d65ba11a11610063578063d65ba11a14610671578063ecf7085814610686578063f23a6e611461069b578063fde813a8146104f0576101e2565b8063c7b9d530146105d2578063ca70baa3146105f1578063d01f63f514610629578063d19a3bb81461064a576101e2565b8063b5f163ff116100d0578063b5f163ff1461052e578063bc197c811461054d578063bdc8144b14610594578063c04dad5d146105b3576101e2565b80638a4adf24146104be5780638adb2ca9146104dd5780639d7fb70c146104f0578063b543503e1461050f576101e2565b80633d6cb575116101795780635d265d3f116101485780635d265d3f146103f457806377ca76b81461043557806381cd63771461045457806385e1f4d014610473576101e2565b80633d6cb5751461038357806346aa2f12146103a257806349317f1d146103c1578063503160d9146103d5576101e2565b80631fe4a686116101b55780631fe4a686146102c557806324c73dda146102fb57806334c041a51461032e57806335ad30b514610361576101e2565b806301ffc9a71461022357806304bd46291461025757806310bc7abf1461028557806318354273146102b1575b3480156101ed575f80fd5b5073bb51273d6c746910c7c06fe718f30c936170fed0365f80375f80365f845af43d5f803e80801561021d573d5ff35b3d5ffd5b005b34801561022e575f80fd5b5061024261023d3660046145a0565b6106c7565b60405190151581526020015b60405180910390f35b348015610262575f80fd5b506102776102713660046145db565b505f1990565b60405190815260200161024e565b348015610290575f80fd5b506102a461029f3660046146c8565b6106fd565b60405161024e91906146f9565b3480156102bc575f80fd5b506102216107ae565b3480156102d0575f80fd5b505f546102e3906001600160a01b031681565b6040516001600160a01b03909116815260200161024e565b348015610306575f80fd5b506102e37f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a251481565b348015610339575f80fd5b506102e37f000000000000000000000000d85ec15a9f814d6173bf1a89273bfb3964aadaec81565b34801561036c575f80fd5b506103756108d9565b60405161024e929190614778565b34801561038e575f80fd5b5061022161039d36600461479c565b610988565b3480156103ad575f80fd5b506102776103bc3660046145db565b61099c565b3480156103cc575f80fd5b50610277610a45565b3480156103e0575f80fd5b506102216103ef36600461479c565b610a5b565b3480156103ff575f80fd5b5060408051600481526024810182526020810180516001600160e01b031663440368a360e01b179052905161024e915f91614800565b348015610440575f80fd5b5061027761044f36600461479c565b610a6c565b34801561045f575f80fd5b5061022161046e36600461481a565b610a8b565b34801561047e575f80fd5b506104a67f000000000000000000000000000000000000000000000000000000000000000181565b6040516001600160401b03909116815260200161024e565b3480156104c9575f80fd5b506001546102e3906001600160a01b031681565b6102216104eb36600461483d565b610b4a565b3480156104fb575f80fd5b5061022161050a36600461479c565b610f7a565b34801561051a575f80fd5b506102216105293660046145db565b610f82565b348015610539575f80fd5b5061027761054836600461479c565b611072565b348015610558575f80fd5b5061057b6105673660046148f7565b63bc197c8160e01b98975050505050505050565b6040516001600160e01b0319909116815260200161024e565b34801561059f575f80fd5b506102216105ae36600461479c565b611081565b3480156105be575f80fd5b506102216105cd3660046149ba565b6110e1565b3480156105dd575f80fd5b506102216105ec3660046145db565b6111a3565b3480156105fc575f80fd5b5060015461061490600160a01b900463ffffffff1681565b60405163ffffffff909116815260200161024e565b348015610634575f80fd5b5061063d611264565b60405161024e9190614a77565b348015610655575f80fd5b506102e373bb51273d6c746910c7c06fe718f30c936170fed081565b34801561067c575f80fd5b5061027760025481565b348015610691575f80fd5b5061027760035481565b3480156106a6575f80fd5b5061057b6106b5366004614a89565b63f23a6e6160e01b9695505050505050565b5f6001600160e01b031982166301ffc9a760e01b14806106f757506001600160e01b03198216630271189760e51b145b92915050565b8051606090806001600160401b0381111561071a5761071a6145f6565b604051908082528060200260200182016040528015610743578160200160208202803683370190505b5091505f5b818110156107a75761077d84828151811061076557610765614aff565b6020026020010151600461127090919063ffffffff16565b83828151811061078f5761078f614aff565b91151560209283029190910190910152600101610748565b5050919050565b6040516321f8a72160e01b81527fbddfa8c39a1f6275bcfb3aa5c70638c466999edbf14e6162d81b3492caca9fce60048201525f907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa158015610832573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108569190614b13565b90507f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb485f6108838261128a565b905080156108d45761089f6001600160a01b03831684836112f2565b6040518181527f76a820ad5e56aebcfa13f60a4ec2e8453550cca0e77446a259782e547c68b32b906020015b60405180910390a15b505050565b606080600660078180548060200260200160405190810160405280929190818152602001828054801561092957602002820191905f5260205f20905b815481526020019060010190808311610915575b505050505091508080548060200260200160405190810160405280929190818152602001828054801561097957602002820191905f5260205f20905b815481526020019060010190808311610965575b50505050509050915091509091565b610990611351565b6109998161138f565b50565b5f807f000000000000000000000000f7de3c70f2db39a188a81052d2f3c8e3e217822a6001600160a01b03166301e1d1146040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109fa573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a1e9190614b2e565b60035490915080821015610a3b57610a368282614b59565b610a3d565b5f5b949350505050565b5f610a4e611351565b610a56611555565b905090565b610a63611351565b6109998161175a565b60068181548110610a7b575f80fd5b5f91825260209091200154905081565b6040516348e4a64960e01b81523360048201527f000000000000000000000000f7de3c70f2db39a188a81052d2f3c8e3e217822a6001600160a01b0316906348e4a649906024015f6040518083038186803b158015610ae8575f80fd5b505afa158015610afa573d5f803e3d5ffd5b505050508063ffffffff165f03610b24576040516360d4aee560e11b815260040160405180910390fd5b6001805463ffffffff909216600160a01b0263ffffffff60a01b19909216919091179055565b5f546001600160a01b03163314610b74576040516312b9d85760e01b815260040160405180910390fd5b5f610b7f8280614b6c565b91505f9050610b916020840184614b6c565b91505f9050610ba36040850185614b6c565b90509050815f03610bc75760405163ec5e1a0b60e01b815260040160405180910390fd5b805f03610be757604051636e1d500960e11b815260040160405180910390fd5b8183141580610c045750610bfe6060850185614b6c565b90508114155b15610c2257604051634456f5e960e11b815260040160405180910390fd5b6002545f90815b85811015610ca2575f5b82811015610c995760068181548110610c4e57610c4e614aff565b5f91825260209091200154610c638980614b6c565b84818110610c7357610c73614aff565b9050602002013503610c915783610c8981614bb1565b945050610c99565b600101610c33565b50600101610c29565b50848214610cc35760405163173b81c360e21b815260040160405180910390fd5b50600190505b83811015610d4657610cdb8580614b6c565b610ce6600184614b59565b818110610cf557610cf5614aff565b60200291909101359050610d098680614b6c565b83818110610d1957610d19614aff565b9050602002013511610d3e5760405163ac5c256f60e01b815260040160405180910390fd5b600101610cc9565b505f5b81811015610e2f5760018110158015610db55750610d6a6040860186614b6c565b610d75600184614b59565b818110610d8457610d84614aff565b90506020020135858060400190610d9b9190614b6c565b83818110610dab57610dab614aff565b9050602002013511155b15610dd3576040516345109f5760e11b815260040160405180910390fd5b610e0a610de36040870187614b6c565b83818110610df357610df3614aff565b90506020020135600461127090919063ffffffff16565b610e275760405163d902535160e01b815260040160405180910390fd5b600101610d49565b505f610e6f610e3e8680614b6c565b610e4b6020890189614b6c565b610e5860408b018b614b6c565b610e6560608d018d614b6c565b8d608001356119f3565b90505f610e9b7fcfa3537c7b7ad87a0dd290c1d493cb256cbf491441572cd66c66c6af6310399b611c69565b9050610eaf81835f01518460200151611cf2565b604051633452c8ed60e21b81526001600160a01b0382169063d14b23b490610edb908590600401614bc9565b5f604051808303815f87803b158015610ef2575f80fd5b505af1158015610f04573d5f803e3d5ffd5b50505050610f727f00000000000000000000000001df6fb6a28a89d6bfa53b2b3f20644abf417678878060400190610f3c9190614b6c565b808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250611d7492505050565b505050505050565b610999611351565b6040516348e4a64960e01b81523360048201527f000000000000000000000000f7de3c70f2db39a188a81052d2f3c8e3e217822a6001600160a01b0316906348e4a649906024015f6040518083038186803b158015610fdf575f80fd5b505afa158015610ff1573d5f803e3d5ffd5b5050506001600160a01b038216905061101d5760405163538ba4f960e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f8e902340d35762a5a36507c20fe38e5d549a721d9f846d6de7f397b5c26ab853906020015b60405180910390a150565b60078181548110610a7b575f80fd5b6001546001600160a01b031633146110ac57604051634f9aa11760e11b815260040160405180910390fd5b60038190556040518181527f5d2e73196f8ba1b44e887e2bcc9bcd1f3e657add341d4a0a632ffff00d6903f290602001611067565b6001546001600160a01b0316331461110c57604051634f9aa11760e11b815260040160405180910390fd5b81518151811461112f57604051634456f5e960e11b815260040160405180910390fd5b805f0361114f576040516342c313c360e11b815260040160405180910390fd5b5f5b8181101561119d5761119584828151811061116e5761116e614aff565b602002602001015184838151811061118857611188614aff565b60200260200101516122b8565b600101611151565b50505050565b6040516348e4a64960e01b81523360048201527f000000000000000000000000f7de3c70f2db39a188a81052d2f3c8e3e217822a6001600160a01b0316906348e4a649906024015f6040518083038186803b158015611200575f80fd5b505afa158015611212573d5f803e3d5ffd5b50505f80546001600160a01b0319166001600160a01b0385169081179091556040519081527f276625620b877c2ddc0a05d68b81971639085fa26d23dfa86eec6460e6fac5b992506020019050611067565b6060610a566004612325565b5f81815260018301602052604081205415155b9392505050565b6040516370a0823160e01b81523060048201525f906001600160a01b038316906370a0823190602401602060405180830381865afa1580156112ce573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f79190614b2e565b6040516001600160a01b038381166024830152604482018390526108d491859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050612331565b33301461138d5760405162461bcd60e51b815260206004820152600560248201526410b9b2b63360d91b60448201526064015b60405180910390fd5b565b6002546060907f000000000000000000000000a195608c2306a26f727d5199d5a382a4508308da9060010361143d575f6113c884612392565b60408051602081018252828152905191925063407c7b1d60e01b916113f09190602401614d0e565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050925061143782825f015183602001516125c0565b506114b8565b5f6114478461261c565b604080516020810182528281529051919250630b0702e960e21b9161146f9190602401614e81565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b03838183161783525050505092506114b682825f01518360200151611cf2565b505b5f80826001600160a01b0316846040516114d29190614f98565b5f604051808303815f865af19150503d805f811461150b576040519150601f19603f3d011682016040523d82523d5f602084013e611510565b606091505b5091509150610f7282826040518060400160405280601a81526020017f43616c6c526576657274576974684e6f52657475726e44617461000000000000815250612d0f565b60025460068054604080516020808402820181019092528281525f948594909385938301828280156115a457602002820191905f5260205f20905b815481526020019060010190808311611590575b505050505090505f7f00000000000000000000000001df6fb6a28a89d6bfa53b2b3f20644abf41767890505f5b8381101561171d575f6115fc8483815181106115ef576115ef614aff565b6020026020010151612d28565b505090505f836001600160a01b031662fdd58e3087868151811061162257611622614aff565b60200260200101516040518363ffffffff1660e01b815260040161165b9291906001600160a01b03929092168252602082015260400190565b602060405180830381865afa158015611676573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061169a9190614b2e565b60405163b7ba28cd60e01b8152600481018290529091506001600160a01b0383169063b7ba28cd90602401602060405180830381865afa1580156116e0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117049190614b2e565b61170e9088614fb3565b965082600101925050506115d1565b506117477f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4861128a565b6117519085614fb3565b94505050505090565b5f6002546001146117ca5763fa0f64eb60e01b604051806020016040528061178185612d5b565b90526040516117939190602401614e81565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261182b565b63b19dcc3360e01b60405180602001604052806117e685613203565b90526040516117f89190602401614d0e565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091525b90507f000000000000000000000000a195608c2306a26f727d5199d5a382a4508308da6118826001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48168285613375565b5f80826001600160a01b03168460405161189c9190614f98565b5f604051808303815f865af19150503d805f81146118d5576040519150601f19603f3d011682016040523d82523d5f602084013e6118da565b606091505b509150915061191f82826040518060400160405280601a81526020017f43616c6c526576657274576974684e6f52657475726e44617461000000000000815250612d0f565b50604051636eb1769f60e11b81523060048201526001600160a01b0384811660248301525f917f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489091169063dd62ed3e90604401602060405180830381865afa15801561198e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119b29190614b2e565b11156119ec576119ec6001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4816845f6133f7565b5050505050565b611a5560405180610140016040528060608152602001606081526020015f81526020015f81526020015f81526020015f6001600160a01b031681526020015f81526020015f6001600160a01b0316815260200160608152602001606081525090565b8989808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250505090825250604080516020808a02828101820190935289825290918a918a9182918501908490808284375f9201829052506020808701959095526001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb481660a087015260c086018790523060e0870152604080518f870281810188019092528f81529195869550611b8094509192508f918f9182918501908490808284375f81840152601f19601f820116905080830192505050505050508b8b808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250899250600191506134869050565b91509150632c1c0ba460e01b82604051602401611b9d9190614e81565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526101008401525f80611be38a8a8a8a6139e9565b91509150611bfc82611bf58584613bbb565b885f613486565b5060405190945063fa0f64eb60e01b90611c1a908690602401614e81565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925261012087015285019290925250919b9a5050505050505050505050565b6040516321f8a72160e01b8152600481018290525f907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa158015611cce573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f79190614b13565b6040516317ea35d960e21b81526001600160a01b037f00000000000000000000000001df6fb6a28a89d6bfa53b2b3f20644abf4176781690635fa8d76490611d4290869086908690600401614fc6565b5f604051808303815f87803b158015611d59575f80fd5b505af1158015611d6b573d5f803e3d5ffd5b50505050505050565b5f6006805480602002602001604051908101604052809291908181526020018280548015611dbf57602002820191905f5260205f20905b815481526020019060010190808311611dab575b5050835186519495509392505f9150505b82811015611e9a575f805b83811015611e2d57868181518110611df557611df5614aff565b6020026020010151868481518110611e0f57611e0f614aff565b602002602001015103611e255760019150611e2d565b600101611ddb565b5080611e9157611e5687868481518110611e4957611e49614aff565b6020026020010151613c6b565b15611e9157848281518110611e6d57611e6d614aff565b602002602001015160405163350085c960e11b815260040161138491815260200190565b50600101611dd0565b5083515f90808203611ebf576040516342c313c360e11b815260040160405180910390fd5b5f816001600160401b03811115611ed857611ed86145f6565b604051908082528060200260200182016040528015611f01578160200160208202803683370190505b5090507f000000000000000000000000d85ec15a9f814d6173bf1a89273bfb3964aadaec5f807f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48815b8681101561217557846001600160a01b031663b5c756978d8381518110611f7357611f73614aff565b60200260200101516040518263ffffffff1660e01b8152600401611f9991815260200190565b602060405180830381865afa158015611fb4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fd89190614ffb565b612012578b8181518110611fee57611fee614aff565b60200260200101516040516317ed28b560e31b815260040161138491815260200190565b6120278c82815181106115ef576115ef614aff565b90505080945050816001600160a01b0316846001600160a01b031663b60262ca6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612074573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120989190614b13565b6001600160a01b0316146120bf576040516307397cd760e01b815260040160405180910390fd5b5f6120d68e8e8481518110611e4957611e49614aff565b60405163b7ba28cd60e01b8152600481018290529091506001600160a01b0386169063b7ba28cd90602401602060405180830381865afa15801561211c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121409190614b2e565b93508387838151811061215557612155614aff565b602090810291909101015261216a848a614fb3565b985050600101611f4a565b505f805b612184600189614b59565b81101561220a576121bd6127108a5f8a85815181106121a5576121a5614aff565b6020026020010151613cd8909392919063ffffffff16565b8782815181106121cf576121cf614aff565b6020026020010181815250508681815181106121ed576121ed614aff565b6020026020010151826122009190614fb3565b9150600101612179565b5061221781612710614b59565b8661222360018a614b59565b8151811061223357612233614aff565b6020026020010181815250508560079080519060200190612255929190614433565b508b516122699060069060208f0190614433565b5060028790556040517fb60570021257b8c021f071d6b761bf920e130dbbd2c819989f690f8337253b88906122a1908e908990614778565b60405180910390a150505050505050505050505050565b5f6122c4600484611270565b9050811515811515146108d45781156122e5576122e083613d33565b6122ee565b6122ee83613d42565b6040805184815283151560208201527ff5b8e2d9dfe40944d8ee0c9b9039acd8516760f92d19ef0f6aba3e0994d7287691016108cb565b60605f61128383613d4d565b5f6123456001600160a01b03841683613da6565b905080515f141580156123695750808060200190518101906123679190614ffb565b155b156108d457604051635274afe760e01b81526001600160a01b0384166004820152602401611384565b61239a61447c565b60065f815481106123ad576123ad614aff565b5f9182526020822001548083526123c390612d28565b505090505f6123f57f00000000000000000000000001df6fb6a28a89d6bfa53b2b3f20644abf417678845f0151613c6b565b60405163b7ba28cd60e01b8152600481018290529091505f906001600160a01b0384169063b7ba28cd90602401602060405180830381865afa15801561243d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124619190614b2e565b60808501516001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb481660209091015284519091505f906124a690613db3565b905080156124e45760808501516001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48166040909101525b81861061250657602085018390526124fc8183613f79565b6040860152612594565b6125108187613f79565b604086810191909152516307c080f960e01b8152600481018790526001600160a01b038516906307c080f990602401602060405180830381865afa15801561255a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061257e9190614b2e565b6020860181905283101561259457602085018390525b50506064606084015250505f60c0820181905260e0820152306101008201819052610120820152919050565b60405163524fca8b60e11b81526001600160a01b03848116600483015260248201849052604482018390527f00000000000000000000000001df6fb6a28a89d6bfa53b2b3f20644abf417678169063a49f951690606401611d42565b6126246144d6565b600254600680546040805160208084028201810190925282815292919083018282801561266e57602002820191905f5260205f20905b81548152602001906001019080831161265a575b505050918452508190506001600160401b0381111561268f5761268f6145f6565b6040519080825280602002602001820160405280156126b8578160200160208202803683370190505b506020830152806001600160401b038111156126d6576126d66145f6565b6040519080825280602002602001820160405280156126ff578160200160208202803683370190505b506060830152806001600160401b0381111561271d5761271d6145f6565b60405190808252806020026020018201604052801561275657816020015b612743614540565b81526020019060019003908161273b5790505b506080830152806001600160401b03811115612774576127746145f6565b60405190808252806020026020018201604052801561279d578160200160208202803683370190505b5060c0830181905260e0830152306101008301819052610120830152806001600160401b038111156127d1576127d16145f6565b6040519080825280602002602001820160405280156127fa578160200160208202803683370190505b5060408301527f00000000000000000000000001df6fb6a28a89d6bfa53b2b3f20644abf4176785f80836001600160401b0381111561283b5761283b6145f6565b604051908082528060200260200182016040528015612864578160200160208202803683370190505b5090505f846001600160401b03811115612880576128806145f6565b6040519080825280602002602001820160405280156128a9578160200160208202803683370190505b5090505f5b858110156129de575f6128cf885f015183815181106115ef576115ef614aff565b505090506128ec86895f01518481518110611e4957611e49614aff565b8483815181106128fe576128fe614aff565b602002602001018181525050806001600160a01b031663b7ba28cd85848151811061292b5761292b614aff565b60200260200101516040518263ffffffff1660e01b815260040161295191815260200190565b602060405180830381865afa15801561296c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129909190614b2e565b8383815181106129a2576129a2614aff565b6020026020010181815250508282815181106129c0576129c0614aff565b6020026020010151856129d39190614fb3565b9450506001016128ae565b505f5b85811015612d04577f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4887608001518281518110612a2057612a20614aff565b6020026020010151602001906001600160a01b031690816001600160a01b0316815250505f612a5d885f015183815181106115ef576115ef614aff565b505090505f612a87895f01518481518110612a7a57612a7a614aff565b6020026020010151613db3565b90508015612aeb577f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4889608001518481518110612ac657612ac6614aff565b6020026020010151604001906001600160a01b031690816001600160a01b0316815250505b858a10612b7857848381518110612b0457612b04614aff565b602002602001015189602001518481518110612b2257612b22614aff565b602002602001018181525050612b5181858581518110612b4457612b44614aff565b6020026020010151613f79565b89604001518481518110612b6757612b67614aff565b602002602001018181525050612cd7565b5f612ba460078581548110612b8f57612b8f614aff565b5f9182526020822001548d9161271090613cd8565b9050612bb08282613f79565b8a604001518581518110612bc657612bc6614aff565b60209081029190910101526040516307c080f960e01b8152600481018290526001600160a01b038416906307c080f990602401602060405180830381865afa158015612c14573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c389190614b2e565b8a602001518581518110612c4e57612c4e614aff565b602002602001018181525050858481518110612c6c57612c6c614aff565b60200260200101518a602001518581518110612c8a57612c8a614aff565b60200260200101511115612cd557858481518110612caa57612caa614aff565b60200260200101518a602001518581518110612cc857612cc8614aff565b6020026020010181815250505b505b606489606001518481518110612cef57612cef614aff565b602090810291909101015250506001016129e1565b505050505050919050565b60608315612d1e575081611283565b6112838383613f90565b8060a081901c60c082901c5f819003612d545760405163030042b760e01b815260040160405180910390fd5b9193909250565b612d636144d6565b6002546006805460408051602080840282018101909252828152929190830182828015612dad57602002820191905f5260205f20905b815481526020019060010190808311612d99575b505050918452508190506001600160401b03811115612dce57612dce6145f6565b604051908082528060200260200182016040528015612df7578160200160208202803683370190505b506020830152806001600160401b03811115612e1557612e156145f6565b604051908082528060200260200182016040528015612e3e578160200160208202803683370190505b506060830152806001600160401b03811115612e5c57612e5c6145f6565b604051908082528060200260200182016040528015612e9557816020015b612e82614540565b815260200190600190039081612e7a5790505b506080830152806001600160401b03811115612eb357612eb36145f6565b604051908082528060200260200182016040528015612edc578160200160208202803683370190505b5060c0830181905260e0830152306101008301819052610120830152806001600160401b03811115612f1057612f106145f6565b604051908082528060200260200182016040528015612f39578160200160208202803683370190505b5060408301525f816001600160401b03811115612f5857612f586145f6565b604051908082528060200260200182016040528015612f8b57816020015b6060815260200190600190039081612f765790505b5090505f6007805480602002602001604051908101604052809291908181526020018280548015612fd957602002820191905f5260205f20905b815481526020019060010190808311612fc5575b505050505090505f5b838110156131d0577f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488560800151828151811061302157613021614aff565b6020026020010151602001906001600160a01b031690816001600160a01b0316815250505f61305e865f015183815181106115ef576115ef614aff565b50509050613087865f0151838151811061307a5761307a614aff565b6020026020010151613fba565b84838151811061309957613099614aff565b60200260200101819052506130d68383815181106130b9576130b9614aff565b60200260200101516127105f8a613cd8909392919063ffffffff16565b866020015183815181106130ec576130ec614aff565b602002602001018181525050806001600160a01b03166307c080f98760200151848151811061311d5761311d614aff565b60200260200101516040518263ffffffff1660e01b815260040161314391815260200190565b602060405180830381865afa15801561315e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131829190614b2e565b8660400151838151811061319857613198614aff565b6020026020010181815250506064866060015183815181106131bc576131bc614aff565b602090810291909101015250600101612fe2565b5082826040516020016131e4929190615061565b60408051601f1981840301815291905261014085015250919392505050565b61320b61447c565b60065f8154811061321e5761321e614aff565b5f91825260208083209091015483528281018490526064606084015260808301516001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb481691015260c0820181905260e08201819052306101008301819052610120830152815161329490612d28565b50506040516307c080f960e01b8152600481018590529091506001600160a01b038216906307c080f990602401602060405180830381865afa1580156132dc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906133009190614b2e565b604083015281515f9061331290613fba565b6040805160018082528183019092529192505f9190816020015b606081526020019060019003908161332c57905050905081815f8151811061335657613356614aff565b60200260200101819052506001816040516020016131e4929190615079565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301525f919085169063dd62ed3e90604401602060405180830381865afa1580156133c2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906133e69190614b2e565b905061119d84846133f78585614fb3565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052613448848261404e565b61119d576040516001600160a01b0384811660248301525f604483015261347c91869182169063095ea7b39060640161131f565b61119d8482612331565b61348e614574565b5f6134976144d6565b868152602081018690525f6134cb7fcfa3537c7b7ad87a0dd290c1d493cb256cbf491441572cd66c66c6af6310399b611c69565b8851909150806001600160401b038111156134e8576134e86145f6565b604051908082528060200260200182016040528015613511578160200160208202803683370190505b506040840152806001600160401b0381111561352f5761352f6145f6565b604051908082528060200260200182016040528015613558578160200160208202803683370190505b506060840152806001600160401b03811115613576576135766145f6565b6040519080825280602002602001820160405280156135af57816020015b61359c614540565b8152602001906001900390816135945790505b5060808401525f816001600160401b038111156135ce576135ce6145f6565b60405190808252806020026020018201604052801561360157816020015b60608152602001906001900390816135ec5790505b5090505f5b82811015613944575f6136248c83815181106115ef576115ef614aff565b505090508815613764575f6136448d8481518110612a7a57612a7a614aff565b905080156136a8577f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488760800151848151811061368357613683614aff565b6020026020010151604001906001600160a01b031690816001600160a01b0316815250505b5f826001600160a01b031663b7ba28cd8e86815181106136ca576136ca614aff565b60200260200101516040518263ffffffff1660e01b81526004016136f091815260200190565b602060405180830381865afa15801561370b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061372f9190614b2e565b905061373b8282613f79565b8860400151858151811061375157613751614aff565b602002602001018181525050505061383f565b6137798c838151811061307a5761307a614aff565b83838151811061378b5761378b614aff565b6020026020010181905250806001600160a01b03166307c080f98c84815181106137b7576137b7614aff565b60200260200101516040518263ffffffff1660e01b81526004016137dd91815260200190565b602060405180830381865afa1580156137f8573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061381c9190614b2e565b8660400151838151811061383257613832614aff565b6020026020010181815250505b8560400151828151811061385557613855614aff565b6020026020010151876138689190614fb3565b9650898660600151838151811061388157613881614aff565b6020026020010181815250507f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48866080015183815181106138c4576138c4614aff565b6020026020010151602001906001600160a01b031690816001600160a01b0316815250507f00000000000000000000000000000000000000000000000000000000000000018660800151838151811061391f5761391f614aff565b60209081029190910101516001600160401b0390911660809091015250600101613606565b50816001600160401b0381111561395d5761395d6145f6565b604051908082528060200260200182016040528015613986578160200160208202803683370190505b5060c0850181905260e08501526001600160a01b03831661010085015230610120850152866139d95781816040516020016139c2929190615061565b60408051601f198184030181529190526101408501525b5050508252909590945092505050565b6060805f83815b81811015613a2d57868682818110613a0a57613a0a614aff565b905060200201355f14613a255782613a2181614bb1565b9350505b6001016139f0565b50816001600160401b03811115613a4657613a466145f6565b604051908082528060200260200182016040528015613a6f578160200160208202803683370190505b509350816001600160401b03811115613a8a57613a8a6145f6565b604051908082528060200260200182016040528015613ab3578160200160208202803683370190505b5092505f805f5b83811015613b8b57888882818110613ad457613ad4614aff565b905060200201355f14613b83578a8a82818110613af357613af3614aff565b90506020020135878481518110613b0c57613b0c614aff565b602002602001018181525050888882818110613b2a57613b2a614aff565b90506020020135868481518110613b4357613b43614aff565b602002602001018181525050888882818110613b6157613b61614aff565b9050602002013582613b739190614fb3565b915082613b7f81614bb1565b9350505b600101613aba565b506127108114613bae576040516314ccf61760e31b815260040160405180910390fd5b5050505094509492505050565b606081516001600160401b03811115613bd657613bd66145f6565b604051908082528060200260200182016040528015613bff578160200160208202803683370190505b5090505f5b8251811015613c6457613c3f838281518110613c2257613c22614aff565b60200260200101516127105f87613cd8909392919063ffffffff16565b828281518110613c5157613c51614aff565b6020908102919091010152600101613c04565b5092915050565b604051627eeac760e11b8152306004820152602481018290525f906001600160a01b0384169062fdd58e90604401602060405180830381865afa158015613cb4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112839190614b2e565b5f80613ce58686866140eb565b90506001836002811115613cfb57613cfb615094565b148015613d1757505f8480613d1257613d126150a8565b868809115b15613d2a57613d27600182614fb3565b90505b95945050505050565b613d3e6004826141d0565b5050565b613d3e6004826141db565b6060815f01805480602002602001604051908101604052809291908181526020018280548015613d9a57602002820191905f5260205f20905b815481526020019060010190808311613d86575b50505050509050919050565b606061128383835f6141e6565b600154604051632ece023360e21b8152600160a01b90910463ffffffff1660048201525f907f000000000000000000000000d85ec15a9f814d6173bf1a89273bfb3964aadaec9082906001600160a01b0383169063bb3808cc90602401602060405180830381865afa158015613e2b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613e4f9190614b13565b90505f613e5b85612d28565b505090505f836001600160a01b031663b85225bb84846001600160a01b03166365cacaa46040518163ffffffff1660e01b8152600401602060405180830381865afa158015613eac573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613ed09190614b13565b604080516001600160a01b0393841660208201529290911690820152606001604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401613f2391815260200190565b602060405180830381865afa158015613f3e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613f629190614b2e565b9050858103613f7057600194505b50505050919050565b5f82613f855781611283565b611283600a83614b59565b815115613fa05781518083602001fd5b8060405162461bcd60e51b815260040161138491906150bc565b60605f613fc683613db3565b613fde5760405180602001604052805f815250614022565b604080516001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48166020820152016040516020818303038152906040525b905082816040516020016140379291906150ce565b604051602081830303815290604052915050919050565b5f805f846001600160a01b0316846040516140699190614f98565b5f604051808303815f865af19150503d805f81146140a2576040519150601f19603f3d011682016040523d82523d5f602084013e6140a7565b606091505b50915091508180156140d15750805115806140d15750808060200190518101906140d19190614ffb565b8015613d2a5750505050506001600160a01b03163b151590565b5f80805f19858709858702925082811083820303915050805f0361412257838281614118576141186150a8565b0492505050611283565b8084116141695760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b6044820152606401611384565b5f8486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091025f889003889004909101858311909403939093029303949094049190911702949350505050565b5f611283838361427f565b5f61128383836142cb565b60608147101561420b5760405163cd78605960e01b8152306004820152602401611384565b5f80856001600160a01b031684866040516142269190614f98565b5f6040518083038185875af1925050503d805f8114614260576040519150601f19603f3d011682016040523d82523d5f602084013e614265565b606091505b50915091506142758683836143ae565b9695505050505050565b5f8181526001830160205260408120546142c457508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556106f7565b505f6106f7565b5f81815260018301602052604081205480156143a5575f6142ed600183614b59565b85549091505f9061430090600190614b59565b905081811461435f575f865f01828154811061431e5761431e614aff565b905f5260205f200154905080875f01848154811061433e5761433e614aff565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080614370576143706150e6565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506106f7565b5f9150506106f7565b6060826143c3576143be8261440a565b611283565b81511580156143da57506001600160a01b0384163b155b1561440357604051639996b31560e01b81526001600160a01b0385166004820152602401611384565b5080611283565b80511561441a5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b828054828255905f5260205f2090810192821561446c579160200282015b8281111561446c578251825591602001919060010190614451565b5061447892915061458c565b5090565b6040518061016001604052805f81526020015f81526020015f81526020015f81526020016144a8614540565b81526060602082018190525f604083018190528183018190526080830181905260a083015260c09091015290565b60405180610160016040528060608152602001606081526020016060815260200160608152602001606081526020016060815260200160608152602001606081526020015f6001600160a01b031681526020015f6001600160a01b03168152602001606081525090565b6040805160c08101825260608082525f6020830181905292820183905281018290526080810182905260a081019190915290565b60405180602001604052806145876144d6565b905290565b5b80821115614478575f815560010161458d565b5f602082840312156145b0575f80fd5b81356001600160e01b031981168114611283575f80fd5b6001600160a01b0381168114610999575f80fd5b5f602082840312156145eb575f80fd5b8135611283816145c7565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715614632576146326145f6565b604052919050565b5f6001600160401b03821115614652576146526145f6565b5060051b60200190565b5f82601f83011261466b575f80fd5b8135602061468061467b8361463a565b61460a565b8083825260208201915060208460051b8701019350868411156146a1575f80fd5b602086015b848110156146bd57803583529183019183016146a6565b509695505050505050565b5f602082840312156146d8575f80fd5b81356001600160401b038111156146ed575f80fd5b610a3d8482850161465c565b602080825282518282018190525f9190848201906040850190845b81811015614732578351151583529284019291840191600101614714565b50909695505050505050565b5f815180845260208085019450602084015f5b8381101561476d57815187529582019590820190600101614751565b509495945050505050565b604081525f61478a604083018561473e565b8281036020840152613d2a818561473e565b5f602082840312156147ac575f80fd5b5035919050565b5f5b838110156147cd5781810151838201526020016147b5565b50505f910152565b5f81518084526147ec8160208601602086016147b3565b601f01601f19169290920160200192915050565b8215158152604060208201525f610a3d60408301846147d5565b5f6020828403121561482a575f80fd5b813563ffffffff81168114611283575f80fd5b5f6020828403121561484d575f80fd5b81356001600160401b03811115614862575f80fd5b820160a08185031215611283575f80fd5b5f8083601f840112614883575f80fd5b5081356001600160401b03811115614899575f80fd5b6020830191508360208260051b85010111156148b3575f80fd5b9250929050565b5f8083601f8401126148ca575f80fd5b5081356001600160401b038111156148e0575f80fd5b6020830191508360208285010111156148b3575f80fd5b5f805f805f805f8060a0898b03121561490e575f80fd5b8835614919816145c7565b97506020890135614929816145c7565b965060408901356001600160401b0380821115614944575f80fd5b6149508c838d01614873565b909850965060608b0135915080821115614968575f80fd5b6149748c838d01614873565b909650945060808b013591508082111561498c575f80fd5b506149998b828c016148ba565b999c989b5096995094979396929594505050565b8015158114610999575f80fd5b5f80604083850312156149cb575f80fd5b82356001600160401b03808211156149e1575f80fd5b6149ed8683870161465c565b9350602091508185013581811115614a03575f80fd5b85019050601f81018613614a15575f80fd5b8035614a2361467b8261463a565b81815260059190911b82018301908381019088831115614a41575f80fd5b928401925b82841015614a68578335614a59816149ad565b82529284019290840190614a46565b80955050505050509250929050565b602081525f611283602083018461473e565b5f805f805f8060a08789031215614a9e575f80fd5b8635614aa9816145c7565b95506020870135614ab9816145c7565b9450604087013593506060870135925060808701356001600160401b03811115614ae1575f80fd5b614aed89828a016148ba565b979a9699509497509295939492505050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215614b23575f80fd5b8151611283816145c7565b5f60208284031215614b3e575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106f7576106f7614b45565b5f808335601e19843603018112614b81575f80fd5b8301803591506001600160401b03821115614b9a575f80fd5b6020019150600581901b36038213156148b3575f80fd5b5f60018201614bc257614bc2614b45565b5060010190565b602081525f8251610140806020850152614be761016085018361473e565b91506020850151601f1980868503016040870152614c05848361473e565b93506040870151606087015260608701516080870152608087015160a087015260a08701519150614c4160c08701836001600160a01b03169052565b60c087015160e087015260e08701519150610100614c69818801846001600160a01b03169052565b80880151925050610120818786030181880152614c8685846147d5565b90880151878203909201848801529350905061427583826147d5565b5f815160c08452614cb660c08501826147d5565b9050602083015160018060a01b038082166020870152806040860151166040870152505060ff60608401511660608501526001600160401b03608084015116608085015260a083015160a08501528091505092915050565b602081525f8251602080840152805160408401526020810151606084015260408101516080840152606081015160a084015260808101516101608060c0860152614d5c6101a0860183614ca2565b915060a0830151603f19808785030160e0880152614d7a84836147d5565b935060c08501519150610100614d938189018415159052565b60e08601519250610120614daa818a018515159052565b90860151925061014090614dc8898301856001600160a01b03169052565b8601516001600160a01b03169388019390935291909301518583039091016101808601529150613d2a81836147d5565b5f8282518085526020808601955060208260051b840101602086015f5b84811015614e4357601f19868403018952614e31838351614ca2565b98840198925090830190600101614e15565b5090979650505050505050565b5f815180845260208085019450602084015f5b8381101561476d578151151587529582019590820190600101614e63565b602081525f82516020808401528051610160806040860152614ea76101a086018361473e565b91506020830151603f1980878503016060880152614ec5848361473e565b93506040850151915080878503016080880152614ee2848361473e565b935060608501519150808785030160a0880152614eff848361473e565b935060808501519150808785030160c0880152614f1c8483614df8565b935060a08501519150808785030160e0880152614f3984836147d5565b935060c08501519150610100818886030181890152614f588584614e50565b945060e086015192506101208289870301818a0152614f778685614e50565b95508187015193506101409150614dc8828a01856001600160a01b03169052565b5f8251614fa98184602087016147b3565b9190910192915050565b808201808211156106f7576106f7614b45565b6001600160a01b03841681526060602082018190525f90614fe99083018561473e565b8281036040840152614275818561473e565b5f6020828403121561500b575f80fd5b8151611283816149ad565b5f8282518085526020808601955060208260051b840101602086015f5b84811015614e4357601f1986840301895261504f8383516147d5565b98840198925090830190600101615033565b828152604060208201525f610a3d6040830184615016565b60ff83168152604060208201525f610a3d6040830184615016565b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52601260045260245ffd5b602081525f61128360208301846147d5565b828152604060208201525f610a3d60408301846147d5565b634e487b7160e01b5f52603160045260245ffdfea264697066735822122084dc9ef8254b7f2d70223b44c21428352171c4b4b68adb9e9c7c089f7146953b64736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a2514000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000fa476c5ec7a43a68e081fd5a33f668f0bd09e126000000000000000000000000701ae9c540ba2144b669f22e650882e7e07cb11f0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000e8d4a5100000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000953757065725553444300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000100000001473b1ce36dec21fc1275c4032731c8469bff371a00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000002710
-----Decoded View---------------
Arg [0] : superRegistry_ (address): 0x17A332dC7B40aE701485023b219E9D6f493a2514
Arg [1] : asset_ (address): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
Arg [2] : strategist_ (address): 0xFa476C5ec7A43a68e081fD5a33f668f0BD09e126
Arg [3] : vaultManager_ (address): 0x701aE9c540ba2144b669F22e650882e7e07cB11F
Arg [4] : name_ (string): SuperUSDC
Arg [5] : depositLimit_ (uint256): 1000000000000
Arg [6] : superformIds_ (uint256[]): 6277101737254839006396113557627089406881862780813070776090
Arg [7] : startingWeights_ (uint256[]): 10000
-----Encoded View---------------
14 Constructor Arguments found :
Arg [0] : 00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a2514
Arg [1] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [2] : 000000000000000000000000fa476c5ec7a43a68e081fd5a33f668f0bd09e126
Arg [3] : 000000000000000000000000701ae9c540ba2144b669f22e650882e7e07cb11f
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [5] : 000000000000000000000000000000000000000000000000000000e8d4a51000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000180
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000009
Arg [9] : 5375706572555344430000000000000000000000000000000000000000000000
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [11] : 000000000000000100000001473b1ce36dec21fc1275c4032731c8469bff371a
Arg [12] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [13] : 0000000000000000000000000000000000000000000000000000000000002710
Deployed Bytecode Sourcemap
214426:38882:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;197696:42:0;213541:14;213290:33;;213522:34;213803:1;213783;213750:14;213730:1;213686:25;213662:5;213631:188;213891:16;213888:1;213885;213870:38;213997:6;214017:68;;;;214136:16;214133:1;214126:27;214017:68;214053:16;214050:1;214043:27;213990:178;;227369:206;;;;;;;;;;-1:-1:-1;227369:206:0;;;;;:::i;:::-;;:::i;:::-;;;566:14:1;;559:22;541:41;;529:2;514:18;227369:206:0;;;;;;;;207029:149;;;;;;;;;;-1:-1:-1;207029:149:0;;;;;:::i;:::-;-1:-1:-1;;;207153:17:0;207029:149;;;;1127:25:1;;;1115:2;1100:18;207029:149:0;981:177:1;225748:388:0;;;;;;;;;;-1:-1:-1;225748:388:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;224316:368::-;;;;;;;;;;;;;:::i;215041:25::-;;;;;;;;;;-1:-1:-1;215041:25:0;;;;-1:-1:-1;;;;;215041:25:0;;;;;;-1:-1:-1;;;;;3709:32:1;;;3691:51;;3679:2;3664:18;215041:25:0;3545:203:1;215231:45:0;;;;;;;;;;;;;;;215347:51;;;;;;;;;;;;;;;226353:160;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;209576:100::-;;;;;;;;;;-1:-1:-1;209576:100:0;;;;;:::i;:::-;;:::i;227617:293::-;;;;;;;;;;-1:-1:-1;227617:293:0;;;;;:::i;:::-;;:::i;210225:117::-;;;;;;;;;;;;;:::i;208992:104::-;;;;;;;;;;-1:-1:-1;208992:104:0;;;;;:::i;:::-;;:::i;204727:318::-;;;;;;;;;;-1:-1:-1;204970:56:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;204970:56:0;-1:-1:-1;;;204970:56:0;;;204727:318;;;;-1:-1:-1;;204727:318:0;:::i;216256:29::-;;;;;;;;;;-1:-1:-1;216256:29:0;;;;;:::i;:::-;;:::i;221023:236::-;;;;;;;;;;-1:-1:-1;221023:236:0;;;;;:::i;:::-;;:::i;214942:32::-;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;6592:31:1;;;6574:50;;6562:2;6547:18;214942:32:0;6430:200:1;215136:27:0;;;;;;;;;;-1:-1:-1;215136:27:0;;;;-1:-1:-1;;;;;215136:27:0;;;221300:2975;;;;;;:::i;:::-;;:::i;210895:100::-;;;;;;;;;;-1:-1:-1;210895:100:0;;;;;:::i;:::-;;:::i;225260:241::-;;;;;;;;;;-1:-1:-1;225260:241:0;;;;;:::i;:::-;;:::i;216360:24::-;;;;;;;;;;-1:-1:-1;216360:24:0;;;;;:::i;:::-;;:::i;226874:301::-;;;;;;;;;;-1:-1:-1;226874:301:0;;;;;:::i;:::-;-1:-1:-1;;;226874:301:0;;;;;;;;;;;;;;-1:-1:-1;;;;;;9262:33:1;;;9244:52;;9232:2;9217:18;226874:301:0;9100:202:1;220599:178:0;;;;;;;;;;-1:-1:-1;220599:178:0;;;;;:::i;:::-;;:::i;224725:494::-;;;;;;;;;;-1:-1:-1;224725:494:0;;;;;:::i;:::-;;:::i;220818:164::-;;;;;;;;;;-1:-1:-1;220818:164:0;;;;;:::i;:::-;;:::i;215466:41::-;;;;;;;;;;-1:-1:-1;215466:41:0;;;;-1:-1:-1;;;215466:41:0;;;;;;;;;10816:10:1;10804:23;;;10786:42;;10774:2;10759:18;215466:41:0;10642:192:1;226177:135:0;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;197636:102::-;;;;;;;;;;;;197696:42;197636:102;;215953:33;;;;;;;;;;;;;;;;216044:27;;;;;;;;;;;;;;;;226559:269;;;;;;;;;;-1:-1:-1;226559:269:0;;;;;:::i;:::-;-1:-1:-1;;;226559:269:0;;;;;;;;;227369:206;227448:4;-1:-1:-1;;;;;;227472:42:0;;-1:-1:-1;;;227472:42:0;;:95;;-1:-1:-1;;;;;;;227518:49:0;;-1:-1:-1;;;227518:49:0;227472:95;227465:102;227369:206;-1:-1:-1;;227369:206:0:o;225748:388::-;225886:20;;225829:27;;225886:20;-1:-1:-1;;;;;225933:18:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;225933:18:0;;225917:34;;225969:9;225964:132;225984:6;225980:1;:10;225964:132;;;226031:53;226067:13;226081:1;226067:16;;;;;;;;:::i;:::-;;;;;;;226031:26;:35;;:53;;;;:::i;:::-;226012:13;226026:1;226012:16;;;;;;;;:::i;:::-;:72;;;:16;;;;;;;;;;;:72;225992:3;;225964:132;;;;226108:20;225748:388;;;:::o;224316:368::-;224399:48;;-1:-1:-1;;;224399:48:0;;224424:22;224399:48;;;1127:25:1;224379:17:0;;224399:13;-1:-1:-1;;;;;224399:24:0;;;;1100:18:1;;224399:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;224379:68;-1:-1:-1;224480:5:0;224458:12;224514:23;224480:5;224514:16;:23::i;:::-;224499:38;-1:-1:-1;224554:9:0;;224550:127;;224580:35;-1:-1:-1;;;;;224580:18:0;;224599:9;224610:4;224580:18;:35::i;:::-;224635:30;;1127:25:1;;;224635:30:0;;1115:2:1;1100:18;224635:30:0;;;;;;;;224550:127;224368:316;;;224316:368::o;226353:160::-;226405:30;226437:25;226483:12;226497:7;226475:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;226353:160;;:::o;209576:100::-;195920:11;:9;:11::i;:::-;209649:19:::1;209660:7;209649:10;:19::i;:::-;209576:100:::0;:::o;227617:293::-;227699:7;227719:19;227741:17;-1:-1:-1;;;;;227741:29:0;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;227808:12;;227719:53;;-1:-1:-1;227838:29:0;;;;:64;;227874:28;227891:11;227874:14;:28;:::i;:::-;227838:64;;;227870:1;227838:64;227831:71;227617:293;-1:-1:-1;;;;227617:293:0:o;210225:117::-;210288:7;195920:11;:9;:11::i;:::-;210315:19:::1;:17;:19::i;:::-;210308:26;;210225:117:::0;:::o;208992:104::-;195920:11;:9;:11::i;:::-;209067:21:::1;209080:7;209067:12;:21::i;216256:29::-:0;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;216256:29:0;:::o;221023:236::-;196097:47;;-1:-1:-1;;;196097:47:0;;196133:10;196097:47;;;3691:51:1;196097:17:0;-1:-1:-1;;;;;196097:35:0;;;;3664:18:1;;196097:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;221143:21:::1;:26;;221168:1;221143:26:::0;221139:48:::1;;221178:9;;-1:-1:-1::0;;;221178:9:0::1;;;;;;;;;;;221139:48;221200:27;:51:::0;;::::1;::::0;;::::1;-1:-1:-1::0;;;221200:51:0::1;-1:-1:-1::0;;;;221200:51:0;;::::1;::::0;;;::::1;::::0;;221023:236::o;221300:2975::-;217124:10;;-1:-1:-1;;;;;217124:10:0;217138;217124:24;217120:93;;217172:29;;-1:-1:-1;;;217172:29:0;;;;;;;;;;;217120:93;221421:24:::1;221448:40;:14:::0;;:40:::1;:::i;:::-;:47:::0;-1:-1:-1;221506:31:0::1;::::0;-1:-1:-1;221540:35:0::1;;::::0;::::1;:14:::0;:35:::1;:::i;:::-;:42:::0;-1:-1:-1;221593:16:0::1;::::0;-1:-1:-1;221612:32:0::1;;::::0;::::1;:14:::0;:32:::1;:::i;:::-;:39;;221593:58;;221668:23;221695:1;221668:28:::0;221664:71:::1;;221705:30;;-1:-1:-1::0;;;221705:30:0::1;;;;;;;;;;;221664:71;221750:8;221762:1;221750:13:::0;221746:53:::1;;221772:27;;-1:-1:-1::0;;;221772:27:0::1;;;;;;;;;;;221746:53;221880:23;221860:16;:43;;:104;;;-1:-1:-1::0;221919:38:0::1;;::::0;::::1;:14:::0;:38:::1;:::i;:::-;:45;;221907:8;:57;;221860:104;221856:167;;;221988:23;;-1:-1:-1::0;;;221988:23:0::1;;;;;;;;;;;221856:167;222159:18;::::0;222104::::1;::::0;;222192:320:::1;222212:16;222208:1;:20;222192:320;;;222259:9;222254:243;222274:11;222270:1;:15;222254:243;;;222366:12;222379:1;222366:15;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;::::1;::::0;222319:40:::1;:14:::0;;:40:::1;:::i;:::-;222360:1;222319:43;;;;;;;:::i;:::-;;;;;;;:62:::0;222315:163:::1;;222410:12:::0;::::1;::::0;::::1;:::i;:::-;;;;222449:5;;222315:163;222287:3;;222254:243;;;-1:-1:-1::0;222230:3:0::1;;222192:320;;;;222546:16;222532:10;:30;222528:115;;222590:37;;-1:-1:-1::0;;;222590:37:0::1;;;;;;;;;;;222528:115;-1:-1:-1::0;222681:1:0::1;::::0;-1:-1:-1;222664:255:0::1;222688:16;222684:1;:20;222664:255;;;222777:40;:14:::0;;:40:::1;:::i;:::-;222818:5;222822:1;222818::::0;:5:::1;:::i;:::-;222777:47;;;;;;;:::i;:::-;;;::::0;;;::::1;;::::0;-1:-1:-1;222730:40:0::1;:14:::0;;:40:::1;:::i;:::-;222771:1;222730:43;;;;;;;:::i;:::-;;;;;;;:94;222726:182;;222852:40;;-1:-1:-1::0;;;222852:40:0::1;;;;;;;;;;;222726:182;222706:3;;222664:255;;;;222936:9;222931:390;222951:8;222947:1;:12;222931:390;;;222990:1;222985;:6;;:88;;;;-1:-1:-1::0;223034:32:0::1;;::::0;::::1;:14:::0;:32:::1;:::i;:::-;223067:5;223071:1;223067::::0;:5:::1;:::i;:::-;223034:39;;;;;;;:::i;:::-;;;;;;;222995:14;:32;;;;;;;;:::i;:::-;223028:1;222995:35;;;;;;;:::i;:::-;;;;;;;:78;;222985:88;222981:167;;;223101:31;;-1:-1:-1::0;;;223101:31:0::1;;;;;;;;;;;222981:167;223167:72;223203:32;;::::0;::::1;:14:::0;:32:::1;:::i;:::-;223236:1;223203:35;;;;;;;:::i;:::-;;;;;;;223167:26;:35;;:72;;;;:::i;:::-;223162:148;;223267:27;;-1:-1:-1::0;;;223267:27:0::1;;;;;;;;;;;223162:148;222961:3;;222931:390;;;-1:-1:-1::0;223387:64:0::1;223454:275;223490:40;:14:::0;;:40:::1;:::i;:::-;223545:35;;::::0;::::1;:14:::0;:35:::1;:::i;:::-;223595:32;;::::0;::::1;:14:::0;:32:::1;:::i;:::-;223642:38;;::::0;::::1;:14:::0;:38:::1;:::i;:::-;223695:14;:23;;;223454:21;:275::i;:::-;223387:342;;223742:18;223763:47;223775:34;223763:11;:47::i;:::-;223742:68;;223867:69;223894:10;223906:4;:8;;;223916:4;:19;;;223867:26;:69::i;:::-;223949:62;::::0;-1:-1:-1;;;223949:62:0;;-1:-1:-1;;;;;223949:56:0;::::1;::::0;::::1;::::0;:62:::1;::::0;224006:4;;223949:62:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;224202:65;224216:16;224234:14;:32;;;;;;;;:::i;:::-;224202:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;224202:13:0::1;::::0;-1:-1:-1;;;224202:65:0:i:1;:::-;221410:2865;;;;;221300:2975:::0;:::o;210895:100::-;195920:11;:9;:11::i;225260:241::-;196097:47;;-1:-1:-1;;;196097:47:0;;196133:10;196097:47;;;3691:51:1;196097:17:0;-1:-1:-1;;;;;196097:35:0;;;;3664:18:1;;196097:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;225356:27:0;::::1;::::0;-1:-1:-1;225352:54:0::1;;225392:14;;-1:-1:-1::0;;;225392:14:0::1;;;;;;;;;;;225352:54;225417:12;:28:::0;;-1:-1:-1;;;;;;225417:28:0::1;-1:-1:-1::0;;;;;225417:28:0;::::1;::::0;;::::1;::::0;;;225463:30:::1;::::0;3691:51:1;;;225463:30:0::1;::::0;3679:2:1;3664:18;225463:30:0::1;;;;;;;;225260:241:::0;:::o;216360:24::-;;;;;;;;;;;;220599:178;217358:12;;-1:-1:-1;;;;;217358:12:0;217374:10;217358:26;217354:85;;217408:19;;-1:-1:-1;;;217408:19:0;;;;;;;;;;;217354:85;220693:12:::1;:28:::0;;;220739:30:::1;::::0;1127:25:1;;;220739:30:0::1;::::0;1115:2:1;1100:18;220739:30:0::1;981:177:1::0;224725:494:0;217358:12;;-1:-1:-1;;;;;217358:12:0;217374:10;217358:26;217354:85;;217408:19;;-1:-1:-1;;;217408:19:0;;;;;;;;;;;217354:85;224929:20;;224974:21;;224964:31;::::1;224960:67;;225004:23;;-1:-1:-1::0;;;225004:23:0::1;;;;;;;;;;;224960:67;225042:6;225052:1;225042:11:::0;225038:41:::1;;225062:17;;-1:-1:-1::0;;;225062:17:0::1;;;;;;;;;;;225038:41;225095:9;225090:122;225110:6;225106:1;:10;225090:122;;;225138:62;225164:13;225178:1;225164:16;;;;;;;;:::i;:::-;;;;;;;225182:14;225197:1;225182:17;;;;;;;;:::i;:::-;;;;;;;225138:25;:62::i;:::-;225118:3;;225090:122;;;;224901:318;224725:494:::0;;:::o;220818:164::-;196097:47;;-1:-1:-1;;;196097:47:0;;196133:10;196097:47;;;3691:51:1;196097:17:0;-1:-1:-1;;;;;196097:35:0;;;;3664:18:1;;196097:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;220906:10:0::1;:24:::0;;-1:-1:-1;;;;;;220906:24:0::1;-1:-1:-1::0;;;;;220906:24:0;::::1;::::0;;::::1;::::0;;;220948:26:::1;::::0;3691:51:1;;;220948:26:0::1;::::0;-1:-1:-1;3679:2:1;3664:18;;-1:-1:-1;220948:26:0::1;3545:203:1::0;226177:135:0;226233:16;226269:35;:26;:33;:35::i;101914:146::-;101991:4;94746:19;;;:12;;;:19;;;;;;:24;;102015:37;102008:44;101914:146;-1:-1:-1;;;101914:146:0:o;240422:130::-;240513:31;;-1:-1:-1;;;240513:31:0;;240538:4;240513:31;;;3691:51:1;240486:7:0;;-1:-1:-1;;;;;240513:16:0;;;;;3664:18:1;;240513:31:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;150150:162::-;150260:43;;-1:-1:-1;;;;;15376:32:1;;;150260:43:0;;;15358:51:1;15425:18;;;15418:34;;;150233:71:0;;150253:5;;150275:14;;;;;15331:18:1;;150260:43:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;150260:43:0;;;;;;;;;;;150233:19;:71::i;196764:99::-;196818:10;196840:4;196818:27;196810:45;;;;-1:-1:-1;;;196810:45:0;;15665:2:1;196810:45:0;;;15647:21:1;15704:1;15684:18;;;15677:29;-1:-1:-1;;;15722:18:1;;;15715:35;15767:18;;196810:45:0;;;;;;;;;196764:99::o;229359:1165::-;229508:18;;229425:21;;229474:17;;229530:1;229508:23;229504:752;;229548:31;229582:40;229614:7;229582:31;:40::i;:::-;229743:39;;;;;;;;;;;229648:149;;229548:74;;-1:-1:-1;;;;229689:52:0;229648:149;;229743:39;229648:149;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;;;;;229648:149:0;;;;;;;-1:-1:-1;;;;;229648:149:0;;;;;;;;;;;229637:160;;229812:68;229838:6;229846;:18;;;229866:6;:13;;;229812:25;:68::i;:::-;229533:359;229504:752;;;229913:30;229946:39;229977:7;229946:30;:39::i;:::-;230105:38;;;;;;;;;;;230011:147;;229913:72;;-1:-1:-1;;;;230052:51:0;230011:147;;230105:38;230011:147;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;;;;;230011:147:0;;;;;;;-1:-1:-1;;;;;230011:147:0;;;;;;;;;;;230000:158;;230173:71;230200:6;230208;:19;;;230229:6;:14;;;230173:26;:71::i;:::-;229898:358;229504:752;230364:12;230378:23;230405:6;-1:-1:-1;;;;;230405:11:0;230417:8;230405:21;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;230363:63;;;;230439:77;230466:7;230475:10;230439:77;;;;;;;;;;;;;;;;;:26;:77::i;230646:839::-;230808:18;;230871:12;230837:46;;;;;;;;;;;;;;;;;;;230707:19;;;;230808:18;;230707:19;;230837:46;;230871:12;230837:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;230894:22;230919:16;230894:41;;230953:9;230948:458;230968:20;230964:1;:24;230948:458;;;231007:17;231030:32;:14;231045:1;231030:17;;;;;;;;:::i;:::-;;;;;;;:30;:32::i;:::-;231006:56;;;;231148:17;231184:14;-1:-1:-1;;;;;231168:41:0;;231218:4;231225:14;231240:1;231225:17;;;;;;;;:::i;:::-;;;;;;;231168:75;;;;;;;;;;;;;;;-1:-1:-1;;;;;15376:32:1;;;;15358:51;;15440:2;15425:18;;15418:34;15346:2;15331:18;;15184:274;231168:75:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;231281:49;;-1:-1:-1;;;231281:49:0;;;;;1127:25:1;;;231148:95:0;;-1:-1:-1;;;;;;231281:38:0;;;;;1100:18:1;;231281:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;231258:72;;;;:::i;:::-;;;231376:3;;;;;230991:415;;230948:458;;;;231454:23;231471:5;231454:16;:23::i;:::-;231432:45;;:19;:45;:::i;:::-;231418:59;;230728:757;;;;230646:839;:::o;228238:1001::-;228306:21;228330:18;;228352:1;228330:23;:448;;228624:50;;;228693:70;;;;;;;;228724:38;228754:7;228724:29;:38::i;:::-;228693:70;;228583:195;;;;;;;;:::i;:::-;;;;-1:-1:-1;;228583:195:0;;;;;;;;;;;;;;-1:-1:-1;;;;;228583:195:0;-1:-1:-1;;;;;;228583:195:0;;;;;;;;;;228330:448;;;228410:51;;;228480:72;;;;;;;;228512:39;228543:7;228512:30;:39::i;:::-;228480:72;;228369:198;;;;;;;;:::i;:::-;;;;-1:-1:-1;;228369:198:0;;;;;;;;;;;;;;-1:-1:-1;;;;;228369:198:0;-1:-1:-1;;;;;;228369:198:0;;;;;;;;;;228330:448;228306:472;-1:-1:-1;228808:17:0;228836:44;-1:-1:-1;;;;;228836:5:0;:27;228808:17;228872:7;228836:27;:44::i;:::-;228989:12;229003:23;229030:6;-1:-1:-1;;;;;229030:11:0;229042:8;229030:21;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;228988:63;;;;229064:77;229091:7;229100:10;229064:77;;;;;;;;;;;;;;;;;:26;:77::i;:::-;-1:-1:-1;229158:38:0;;-1:-1:-1;;;229158:38:0;;229182:4;229158:38;;;22358:34:1;-1:-1:-1;;;;;22428:15:1;;;22408:18;;;22401:43;229199:1:0;;229158:5;:15;;;;;;22293:18:1;;229158:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:42;229154:77;;;229202:29;-1:-1:-1;;;;;229202:5:0;:18;229221:6;229229:1;229202:18;:29::i;:::-;228295:944;;;;228238:1001;:::o;241205:1738::-;241530:64;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;241530:64:0;241623:26;;241612:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;241612:37:0;;;-1:-1:-1;241660:43:0;;;;;;;;;;;;;;;;;;;;241682:21;;;;;;241660:43;;;241682:21;;241660:43;241682:21;241660:43;;;;;;;;-1:-1:-1;241660:19:0;;;;:43;;;;-1:-1:-1;;;;;241742:5:0;241714:34;:17;;;:34;241800:13;;;:25;;;241902:4;241869:22;;;:38;242006:106;;;;;;;;;;;;;;;;;241660:43;;;;-1:-1:-1;242006:106:0;;-1:-1:-1;242006:106:0;;-1:-1:-1;242045:26:0;;;;;;242006:106;;;242045:26;;242006:106;242045:26;242006:106;;;;;;;;;;;;;;;;;;;;;;;;;;242073:21;;242006:106;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;242096:9:0;;-1:-1:-1;242107:4:0;;-1:-1:-1;242006:38:0;;-1:-1:-1;242006:106:0:i;:::-;241920:192;;;;242218:51;;;242271:3;242195:80;;;;;;;;:::i;:::-;;;;-1:-1:-1;;242195:80:0;;;;;;;;;;;;;;-1:-1:-1;;;;;242195:80:0;-1:-1:-1;;;;;;242195:80:0;;;;;;;;;;242179:13;;;:96;-1:-1:-1;;242448:67:0;242470:18;;242490:24;;242448:21;:67::i;:::-;242359:156;;;;242537:157;242590:20;242612:53;242630:17;242649:15;242612:17;:53::i;:::-;242667:9;242678:5;242537:38;:157::i;:::-;-1:-1:-1;242780:79:0;;242528:166;;-1:-1:-1;;;;242803:50:0;242780:79;;242528:166;;242780:79;;;:::i;:::-;;;;-1:-1:-1;;242780:79:0;;;;;;;;;;;;;;-1:-1:-1;;;;;242780:79:0;-1:-1:-1;;;;;;242780:79:0;;;;;;;;;;242753:24;;;:106;242870:45;;:65;;;;-1:-1:-1;242753:4:0;;241205:1738;-1:-1:-1;;;;;;;;;;;241205:1738:0:o;239219:121::-;239303:29;;-1:-1:-1;;;239303:29:0;;;;;1127:25:1;;;239276:7:0;;239303:13;-1:-1:-1;;;;;239303:24:0;;;;1100:18:1;;239303:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;239568:274::-;239748:86;;-1:-1:-1;;;239748:86:0;;-1:-1:-1;;;;;239764:16:0;239748:52;;;;:86;;239801:7;;239810:13;;239825:8;;239748:86;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;239568:274;;;:::o;248529:3165::-;248674:36;248713:12;248674:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;248804:26:0;;248870:25;;248674:51;;-1:-1:-1;248804:26:0;248870:25;-1:-1:-1;248780:21:0;;-1:-1:-1;;248906:801:0;248926:13;248922:1;:17;248906:801;;;248957:10;249044:9;249039:285;249059:18;249055:1;:22;249039:285;;;249129:18;249148:1;249129:21;;;;;;;;:::i;:::-;;;;;;;249103:19;249123:1;249103:22;;;;;;;;:::i;:::-;;;;;;;:47;249099:136;;249183:4;249175:12;;249210:5;;249099:136;249286:3;;249039:285;;;;249416:5;249411:221;;249446:65;249471:15;249488:19;249508:1;249488:22;;;;;;;;:::i;:::-;;;;;;;249446:24;:65::i;:::-;:70;249442:175;;249574:19;249594:1;249574:22;;;;;;;;:::i;:::-;;;;;;;249548:49;;-1:-1:-1;;;249548:49:0;;;;;;1127:25:1;;1115:2;1100:18;;981:177;249442:175:0;-1:-1:-1;249677:3:0;;248906:801;;;-1:-1:-1;249766:25:0;;249719:19;;249806:11;;;249802:41;;249826:17;;-1:-1:-1;;;249826:17:0;;;;;;;;;;;249802:41;249856:27;249900:6;-1:-1:-1;;;;;249886:21:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;249886:21:0;-1:-1:-1;249856:51:0;-1:-1:-1;250066:18:0;250020:25;;250177:5;250020:25;250258:716;250278:6;250274:1;:10;250258:716;;;250307:7;-1:-1:-1;;;;;250307:19:0;;250327:18;250346:1;250327:21;;;;;;;;:::i;:::-;;;;;;;250307:42;;;;;;;;;;;;;1127:25:1;;1115:2;1100:18;;981:177;250307:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;250302:138;;250402:18;250421:1;250402:21;;;;;;;;:::i;:::-;;;;;;;250377:47;;-1:-1:-1;;;250377:47:0;;;;;;1127:25:1;;1115:2;1100:18;;981:177;250302:138:0;250472:36;:18;250491:1;250472:21;;;;;;;;:::i;:36::-;250456:52;;;;;;;250569:10;-1:-1:-1;;;;;250529:50:0;250539:9;-1:-1:-1;;;;;250529:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;250529:50:0;;250525:132;;250607:34;;-1:-1:-1;;;250607:34:0;;;;;;;;;;;250525:132;250673:15;250691:64;250716:15;250733:18;250752:1;250733:21;;;;;;;;:::i;250691:64::-;250778:47;;-1:-1:-1;;;250778:47:0;;;;;1127:25:1;;;250673:82:0;;-1:-1:-1;;;;;;250778:38:0;;;;;1100:18:1;;250778:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;250770:55;;250858:5;250842:10;250853:1;250842:13;;;;;;;;:::i;:::-;;;;;;;;;;:21;250878:20;250893:5;250878:20;;:::i;:::-;;-1:-1:-1;;250944:3:0;;250258:716;;;;251041:27;251084:9;251079:258;251099:10;251108:1;251099:6;:10;:::i;:::-;251095:1;:14;251079:258;;;251143:67;215638:6;251178:11;251191:18;251143:10;251154:1;251143:13;;;;;;;;:::i;:::-;;;;;;;:20;;:67;;;;;;:::i;:::-;251127:10;251138:1;251127:13;;;;;;;;:::i;:::-;;;;;;:83;;;;;251248:10;251259:1;251248:13;;;;;;;;:::i;:::-;;;;;;;251225:36;;;;;:::i;:::-;;-1:-1:-1;251307:3:0;;251079:258;;;-1:-1:-1;251437:34:0;251452:19;215638:6;251437:34;:::i;:::-;251412:10;251423;251432:1;251423:6;:10;:::i;:::-;251412:22;;;;;;;;:::i;:::-;;;;;;:59;;;;;251527:10;251517:7;:20;;;;;;;;;;;;:::i;:::-;-1:-1:-1;251548:33:0;;;;:12;;:33;;;;;:::i;:::-;-1:-1:-1;251592:18:0;:27;;;251637:49;;;;;;251655:18;;251675:10;;251637:49;:::i;:::-;;;;;;;;248623:3071;;;;;;;;;;;248529:3165;;:::o;251881:549::-;251979:25;252007:49;:26;252043:12;252007:35;:49::i;:::-;251979:77;;252150:14;252126:38;;:20;:38;;;252122:301;;252185:14;252181:159;;;252220:29;252236:12;252220:15;:29::i;:::-;252181:159;;;252290:34;252311:12;252290:20;:34::i;:::-;252361:50;;;23440:25:1;;;23508:14;;23501:22;23496:2;23481:18;;23474:50;252361::0;;23413:18:1;252361:50:0;23272:258:1;103301:307:0;103361:16;103390:22;103415:19;103423:3;103415:7;:19::i;152961:638::-;153385:23;153411:33;-1:-1:-1;;;;;153411:27:0;;153439:4;153411:27;:33::i;:::-;153385:59;;153459:10;:17;153480:1;153459:22;;:57;;;;;153497:10;153486:30;;;;;;;;;;;;:::i;:::-;153485:31;153459:57;153455:137;;;153540:40;;-1:-1:-1;;;153540:40:0;;-1:-1:-1;;;;;3709:32:1;;153540:40:0;;;3691:51:1;3664:18;;153540:40:0;3545:203:1;236904:1414:0;236985:31;;:::i;:::-;237050:12;237063:1;237050:15;;;;;;;;:::i;:::-;;;;;;;;;;237029:36;;;237100:33;;:31;:33::i;:::-;237076:57;;;;237179:17;237199:62;237224:16;237242:6;:18;;;237199:24;:62::i;:::-;237295:49;;-1:-1:-1;;;237295:49:0;;;;;1127:25:1;;;237179:82:0;;-1:-1:-1;237272:20:0;;-1:-1:-1;;;;;237295:38:0;;;;;1100:18:1;;237295:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;237387:17;;;;-1:-1:-1;;;;;237421:5:0;237387:40;:23;;;;:40;237471:18;;237272:72;;-1:-1:-1;237438:14:0;;237455:35;;:15;:35::i;:::-;237438:52;;237507:9;237503:89;;;237533:17;;;;-1:-1:-1;;;;;237574:5:0;237533:47;:30;;;;:47;237503:89;237660:12;237649:7;:23;237645:422;;237689:13;;;:25;;;237751:35;237762:9;237773:12;237751:10;:35::i;:::-;237729:19;;;:57;237645:422;;;237841:30;237852:9;237863:7;237841:10;:30::i;:::-;237819:19;;;;:52;;;;237902:46;-1:-1:-1;;;237902:46:0;;;;;1127:25:1;;;-1:-1:-1;;;;;237902:37:0;;;;;1100:18:1;;237902:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;237886:13;;;:62;;;237969:25;-1:-1:-1;237965:91:0;;;238015:13;;;:25;;;237965:91;-1:-1:-1;;215750:3:0;238079:18;;;:33;-1:-1:-1;;238143:5:0;238123:17;;;:25;;;238159:17;;;:25;238228:4;238195:22;;;:38;;;238244:24;;;:40;238079:6;236904:1414;-1:-1:-1;236904:1414:0:o;240065:202::-;240176:83;;-1:-1:-1;;;240176:83:0;;-1:-1:-1;;;;;23755:32:1;;;240176:83:0;;;23737:51:1;23804:18;;;23797:34;;;23847:18;;;23840:34;;;240192:16:0;240176:51;;;;23710:18:1;;240176:83:0;23535:345:1;234246:2650:0;234326:30;;:::i;:::-;234400:18;;234453:12;234431:34;;;;;;;;;;;;;;;;;;;;234453:12;234431:34;;;234453:12;234431:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;234431:34:0;;;-1:-1:-1;234507:20:0;;-1:-1:-1;;;;;;234493:35:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;234493:35:0;-1:-1:-1;234476:14:0;;;:52;234575:20;-1:-1:-1;;;;;234561:35:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;234561:35:0;-1:-1:-1;234539:19:0;;;:57;234645:20;-1:-1:-1;;;;;234628:38:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;234607:18:0;;;:59;234709:20;-1:-1:-1;;;;;234698:32:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;234698:32:0;-1:-1:-1;234677:18:0;;;:53;;;234741:18;;;:39;234824:4;234791:22;;;:38;;;234840:24;;;:40;234928:20;-1:-1:-1;;;;;234914:35:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;234914:35:0;-1:-1:-1;234891:20:0;;;:58;234987:16;234962:22;;235096:20;-1:-1:-1;;;;;235082:35:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;235082:35:0;;235052:65;;235128:30;235175:20;-1:-1:-1;;;;;235161:35:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;235161:35:0;;235128:68;;235258:9;235253:433;235273:20;235269:1;:24;235253:433;;;235312:17;235335:37;:6;:19;;;235355:1;235335:22;;;;;;;;:::i;:37::-;235311:61;;;;235405:64;235430:14;235446:6;:19;;;235466:1;235446:22;;;;;;;;:::i;235405:64::-;235389:10;235400:1;235389:13;;;;;;;;:::i;:::-;;;;;;:80;;;;;235513:9;-1:-1:-1;;;;;235503:38:0;;235542:10;235553:1;235542:13;;;;;;;;:::i;:::-;;;;;;;235503:53;;;;;;;;;;;;;1127:25:1;;1115:2;1100:18;;981:177;235503:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;235484:13;235498:1;235484:16;;;;;;;;:::i;:::-;;;;;;:72;;;;;235594:13;235608:1;235594:16;;;;;;;;:::i;:::-;;;;;;;235571:39;;;;;:::i;:::-;;-1:-1:-1;;235656:3:0;;235253:433;;;;235744:9;235739:1124;235759:20;235755:1;:24;235739:1124;;;235835:5;235797:6;:18;;;235816:1;235797:21;;;;;;;;:::i;:::-;;;;;;;:27;;:44;-1:-1:-1;;;;;235797:44:0;;;-1:-1:-1;;;;;235797:44:0;;;;;235859:17;235882:37;:6;:19;;;235902:1;235882:22;;;;;;;;:::i;:37::-;235858:61;;;;235936:14;235953:39;235969:6;:19;;;235989:1;235969:22;;;;;;;;:::i;:::-;;;;;;;235953:15;:39::i;:::-;235936:56;;236013:9;236009:101;;;236088:5;236043:6;:18;;;236062:1;236043:21;;;;;;;;:::i;:::-;;;;;;;:34;;:51;-1:-1:-1;;;;;236043:51:0;;;-1:-1:-1;;;;;236043:51:0;;;;;236009:101;236141:19;236130:7;:30;236126:608;;236201:10;236212:1;236201:13;;;;;;;;:::i;:::-;;;;;;;236181:6;:14;;;236196:1;236181:17;;;;;;;;:::i;:::-;;;;;;:33;;;;;236259:39;236270:9;236281:13;236295:1;236281:16;;;;;;;;:::i;:::-;;;;;;;236259:10;:39::i;:::-;236233:6;:20;;;236254:1;236233:23;;;;;;;;:::i;:::-;;;;;;:65;;;;;236126:608;;;236339:17;236359:60;236374:7;236382:1;236374:10;;;;;;;;:::i;:::-;;;;;;;;;;236359:7;;215638:6;;236359:14;:60::i;:::-;236339:80;;236464:32;236475:9;236486;236464:10;:32::i;:::-;236438:6;:20;;;236459:1;236438:23;;;;;;;;:::i;:::-;;;;;;;;;;:58;236535:48;;-1:-1:-1;;;236535:48:0;;;;;1127:25:1;;;-1:-1:-1;;;;;236535:37:0;;;;;1100:18:1;;236535:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;236515:6;:14;;;236530:1;236515:17;;;;;;;;:::i;:::-;;;;;;:68;;;;;236628:10;236639:1;236628:13;;;;;;;;:::i;:::-;;;;;;;236608:6;:14;;;236623:1;236608:17;;;;;;;;:::i;:::-;;;;;;;:33;236604:115;;;236686:10;236697:1;236686:13;;;;;;;;:::i;:::-;;;;;;;236666:6;:14;;;236681:1;236666:17;;;;;;;;:::i;:::-;;;;;;:33;;;;;236604:115;236320:414;236126:608;215750:3;236750:6;:19;;;236770:1;236750:22;;;;;;;;:::i;:::-;;;;;;;;;;:37;-1:-1:-1;;236833:3:0;;235739:1124;;;;236875:13;;;;;234246:2650;;;:::o;75293:305::-;75443:12;75472:7;75468:123;;;-1:-1:-1;75503:10:0;75496:17;;75468:123;75546:33;75554:10;75566:12;75546:7;:33::i;117649:428::-;117855:12;117927:3;117911:19;;;117976:3;117960:19;;;117743:18;117997:13;;;117993:77;;118034:24;;-1:-1:-1;;;118034:24:0;;;;;;;;;;;117993:77;117649:428;;;;;:::o;231699:1616::-;231778:30;;:::i;:::-;231852:18;;231905:12;231883:34;;;;;;;;;;;;;;;;;;;;231905:12;231883:34;;;231905:12;231883:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;231883:34:0;;;-1:-1:-1;231959:20:0;;-1:-1:-1;;;;;;231945:35:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;231945:35:0;-1:-1:-1;231928:14:0;;;:52;232027:20;-1:-1:-1;;;;;232013:35:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;232013:35:0;-1:-1:-1;231991:19:0;;;:57;232097:20;-1:-1:-1;;;;;232080:38:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;232059:18:0;;;:59;232161:20;-1:-1:-1;;;;;232150:32:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;232150:32:0;-1:-1:-1;232129:18:0;;;:53;;;232193:18;;;:39;232276:4;232243:22;;;:38;;;232292:24;;;:40;232380:20;-1:-1:-1;;;;;232366:35:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;232366:35:0;-1:-1:-1;232343:20:0;;;:58;232414:27;232456:20;-1:-1:-1;;;;;232444:33:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;232414:63;;232490:26;232519:7;232490:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;232542:9;232537:665;232557:20;232553:1;:24;232537:665;;;232633:5;232595:6;:18;;;232614:1;232595:21;;;;;;;;:::i;:::-;;;;;;;:27;;:44;-1:-1:-1;;;;;232595:44:0;;;-1:-1:-1;;;;;232595:44:0;;;;;232657:17;232680:37;:6;:19;;;232700:1;232680:22;;;;;;;;:::i;:37::-;232656:61;;;;232752:64;232793:6;:19;;;232813:1;232793:22;;;;;;;;:::i;:::-;;;;;;;232752:40;:64::i;:::-;232734:12;232747:1;232734:15;;;;;;;;:::i;:::-;;;;;;:82;;;;232915:62;232930:9;232940:1;232930:12;;;;;;;;:::i;:::-;;;;;;;215638:6;232958:18;232915:7;:14;;:62;;;;;;:::i;:::-;232895:6;:14;;;232910:1;232895:17;;;;;;;;:::i;:::-;;;;;;:82;;;;;233028:9;-1:-1:-1;;;;;233018:37:0;;233056:6;:14;;;233071:1;233056:17;;;;;;;;:::i;:::-;;;;;;;233018:56;;;;;;;;;;;;;1127:25:1;;1115:2;1100:18;;981:177;233018:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;232992:6;:20;;;233013:1;232992:23;;;;;;;;:::i;:::-;;;;;;:82;;;;;215750:3;233089:6;:19;;;233109:1;233089:22;;;;;;;;:::i;:::-;;;;;;;;;;:37;-1:-1:-1;233172:3:0;;232537:665;;;;233248:20;233270:12;233237:46;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;233237:46:0;;;;;;;;;233214:20;;;:69;-1:-1:-1;233214:6:0;;231699:1616;-1:-1:-1;;;231699:1616:0:o;233323:915::-;233403:31;;:::i;:::-;233468:12;233481:1;233468:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;233447:36;;233494:13;;;:23;;;215750:3;233528:18;;;:33;233572:17;;;;-1:-1:-1;;;;;233606:5:0;233572:40;:23;;:40;233623:17;;;:25;;;233659:17;;;:25;;;233728:4;233695:22;;;:38;;;233744:24;;;:40;233821:18;;:33;;:31;:33::i;:::-;-1:-1:-1;;233887:46:0;;-1:-1:-1;;;233887:46:0;;;;;1127:25:1;;;233797:57:0;;-1:-1:-1;;;;;;233887:37:0;;;;;1100:18:1;;233887:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;233865:19;;;:68;234013:18;;233944:25;;233972:60;;:40;:60::i;:::-;234078:14;;;234090:1;234078:14;;;;;;;;;233944:88;;-1:-1:-1;234043:32:0;;234078:14;;;;;;;;;;;;;;;;;;;;;234043:49;;234126:12;234103:17;234121:1;234103:20;;;;;;;;:::i;:::-;;;;;;:35;;;;234183:1;234186:17;234172:32;;;;;;;;;:::i;150944:228::-;151064:39;;-1:-1:-1;;;151064:39:0;;151088:4;151064:39;;;22358:34:1;-1:-1:-1;;;;;22428:15:1;;;22408:18;;;22401:43;151041:20:0;;151064:15;;;;;;22293:18:1;;151064:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;151041:62;-1:-1:-1;151114:50:0;151127:5;151134:7;151143:20;151158:5;151041:62;151143:20;:::i;:::-;152299:47;;;-1:-1:-1;;;;;15376:32:1;;152299:47:0;;;15358:51:1;15425:18;;;;15418:34;;;152299:47:0;;;;;;;;;;15331:18:1;;;;152299:47:0;;;;;;;;-1:-1:-1;;;;;152299:47:0;-1:-1:-1;;;152299:47:0;;;152364:44;152314:13;152299:47;152364:23;:44::i;:::-;152359:204;;152452:43;;-1:-1:-1;;;;;15376:32:1;;;152452:43:0;;;15358:51:1;152492:1:0;15425:18:1;;;15418:34;152425:71:0;;152445:5;;152467:13;;;;;15331:18:1;;152452:43:0;15184:274:1;152425:71:0;152511:40;152531:5;152538:12;152511:19;:40::i;243365:2476::-;243602:41;;:::i;:::-;243645:25;243688:28;;:::i;:::-;243727:33;;;243771:12;;;:23;;;243727:17;243828:47;243840:34;243828:11;:47::i;:::-;243919:20;;243807:68;;-1:-1:-1;243919:20:0;-1:-1:-1;;;;;243971:35:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;243971:35:0;-1:-1:-1;243950:18:0;;;:56;244051:20;-1:-1:-1;;;;;244037:35:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;244037:35:0;-1:-1:-1;244017:17:0;;;:55;244119:20;-1:-1:-1;;;;;244102:38:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;244083:16:0;;;:57;244151:27;244193:20;-1:-1:-1;;;;;244181:33:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;244151:63;;244232:9;244227:1083;244247:20;244243:1;:24;244227:1083;;;244286:17;244309:31;:13;244323:1;244309:16;;;;;;;;:::i;:31::-;244285:55;;;;244361:11;244357:654;;;244439:14;244456:33;244472:13;244486:1;244472:16;;;;;;;;:::i;244456:33::-;244439:50;;244514:9;244510:107;;;244591:5;244548:4;:16;;;244565:1;244548:19;;;;;;;;:::i;:::-;;;;;;;:32;;:49;-1:-1:-1;;;;;244548:49:0;;;-1:-1:-1;;;;;244548:49:0;;;;;244510:107;244637:17;244667:9;-1:-1:-1;;;;;244657:38:0;;244696:8;244705:1;244696:11;;;;;;;;:::i;:::-;;;;;;;244657:51;;;;;;;;;;;;;1127:25:1;;1115:2;1100:18;;981:177;244657:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;244637:71;;244751:32;244762:9;244773;244751:10;:32::i;:::-;244727:4;:18;;;244746:1;244727:21;;;;;;;;:::i;:::-;;;;;;:56;;;;;244374:425;;244357:654;;;244842:58;244883:13;244897:1;244883:16;;;;;;;;:::i;244842:58::-;244824:12;244837:1;244824:15;;;;;;;;:::i;:::-;;;;;;:76;;;;244955:9;-1:-1:-1;;;;;244945:37:0;;244983:8;244992:1;244983:11;;;;;;;;:::i;:::-;;;;;;;244945:50;;;;;;;;;;;;;1127:25:1;;1115:2;1100:18;;981:177;244945:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;244921:4;:18;;;244940:1;244921:21;;;;;;;;:::i;:::-;;;;;;:74;;;;;244357:654;245048:4;:18;;;245067:1;245048:21;;;;;;;;:::i;:::-;;;;;;;245027:42;;;;;:::i;:::-;;;245109:9;245086:4;:17;;;245104:1;245086:20;;;;;;;;:::i;:::-;;;;;;:32;;;;;245169:5;245133:4;:16;;;245150:1;245133:19;;;;;;;;:::i;:::-;;;;;;;:25;;:42;-1:-1:-1;;;;;245133:42:0;;;-1:-1:-1;;;;;245133:42:0;;;;;245226:8;245190:4;:16;;;245207:1;245190:19;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;245190:44:0;;;:33;;;;:44;-1:-1:-1;245280:3:0;;244227:1083;;;;245352:20;-1:-1:-1;;;;;245341:32:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;245341:32:0;-1:-1:-1;245322:16:0;;;:51;;;245384:16;;;:35;-1:-1:-1;;;;;245501:33:0;;:20;;;:33;245669:4;245636:22;;;:38;245692:11;245687:112;;245752:20;245774:12;245741:46;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;245741:46:0;;;;;;;;;245720:18;;;:67;245687:112;-1:-1:-1;;;245809:24:0;;:3;;243365:2476;;-1:-1:-1;243365:2476:0;-1:-1:-1;;;243365:2476:0:o;247374:939::-;247543:28;;247623:13;247664:8;247623:13;247690:123;247710:6;247706:1;:10;247690:123;;;247742:8;;247751:1;247742:11;;;;;;;:::i;:::-;;;;;;;247757:1;247742:16;247738:64;;247779:7;;;;:::i;:::-;;;;247738:64;247718:3;;247690:123;;;;247853:5;-1:-1:-1;;;;;247839:20:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;247839:20:0;;247825:34;;247902:5;-1:-1:-1;;;;;247888:20:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;247888:20:0;;247870:38;;247921:9;247941:19;247976:9;247971:267;247991:6;247987:1;:10;247971:267;;;248023:8;;248032:1;248023:11;;;;;;;:::i;:::-;;;;;;;248038:1;248023:16;248019:208;;248077:13;;248091:1;248077:16;;;;;;;:::i;:::-;;;;;;;248060:11;248072:1;248060:14;;;;;;;;:::i;:::-;;;;;;:33;;;;;248133:8;;248142:1;248133:11;;;;;;;:::i;:::-;;;;;;;248112:15;248128:1;248112:18;;;;;;;;:::i;:::-;;;;;;:32;;;;;248178:8;;248187:1;248178:11;;;;;;;:::i;:::-;;;;;;;248163:26;;;;;:::i;:::-;;-1:-1:-1;248208:3:0;;;;:::i;:::-;;;;248019:208;247999:3;;247971:267;;;;215638:6;248252:11;:27;248248:57;;248288:17;;-1:-1:-1;;;248288:17:0;;;;;;;;;;;248248:57;247612:701;;;;247374:939;;;;;;;:::o;246646:411::-;246803:24;246869:8;:15;-1:-1:-1;;;;;246855:30:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;246855:30:0;;246845:40;;246901:9;246896:154;246916:8;:15;246912:1;:19;246896:154;;;246966:72;246992:8;247001:1;246992:11;;;;;;;;:::i;:::-;;;;;;;215638:6;247019:18;246966;:25;;:72;;;;;;:::i;:::-;246953:7;246961:1;246953:10;;;;;;;;:::i;:::-;;;;;;;;;;:85;246933:3;;246896:154;;;;246646:411;;;;:::o;240560:206::-;240689:69;;-1:-1:-1;;;240689:69:0;;240739:4;240689:69;;;15358:51:1;15425:18;;;15418:34;;;240662:7:0;;-1:-1:-1;;;;;240689:41:0;;;;;15331:18:1;;240689:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;83261:305::-;83362:7;83382:14;83399:25;83406:1;83409;83412:11;83399:6;:25::i;:::-;83382:42;-1:-1:-1;83451:11:0;83439:8;:23;;;;;;;;:::i;:::-;;:56;;;;;83494:1;83479:11;83466:25;;;;;:::i;:::-;83476:1;83473;83466:25;:29;83439:56;83435:100;;;83512:11;83522:1;83512:11;;:::i;:::-;;;83435:100;83552:6;83261:305;-1:-1:-1;;;;;83261:305:0:o;252550:117::-;252616:43;:26;252647:11;252616:30;:43::i;:::-;;252550:117;:::o;252795:125::-;252866:46;:26;252900:11;252866:33;:46::i;95997:111::-;96053:16;96089:3;:11;;96082:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95997:111;;;:::o;16504:153::-;16579:12;16611:38;16633:6;16641:4;16647:1;16611:21;:38::i;238521:628::-;238772:27;;238742:58;;-1:-1:-1;;;238742:58:0;;-1:-1:-1;;;238772:27:0;;;;;238742:58;;;10786:42:1;238591:14:0;;238678:18;;238591:14;;-1:-1:-1;;;;;238742:29:0;;;;;10759:18:1;;238742:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;238710:90;;238814:17;238837:27;:12;:25;:27::i;:::-;238813:51;;;;238877:19;238899:7;-1:-1:-1;;;;;238899:44:0;;238979:21;239012:9;-1:-1:-1;;;;;239002:36:0;;:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;238968:73;;;-1:-1:-1;;;;;22376:15:1;;;238968:73:0;;;22358:34:1;22428:15;;;;22408:18;;;22401:43;22293:18;;238968:73:0;;;;;;;;;;;;238958:84;;;;;;238899:154;;;;;;;;;;;;;1127:25:1;;1115:2;1100:18;;981:177;238899:154:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;238877:176;;239085:12;239070:11;:27;239066:76;;239126:4;239114:16;;239066:76;238607:542;;;;238521:628;;;:::o;253147:158::-;253222:7;253249:9;:48;;253291:6;253249:48;;;253261:27;215883:6;253261;:27;:::i;75606:552::-;75767:17;;:21;75763:388;;75999:10;75993:17;76056:15;76043:10;76039:2;76035:19;76028:44;75763:388;76126:12;76119:20;;-1:-1:-1;;;76119:20:0;;;;;;;;:::i;246022:385::-;246117:12;246249:22;246274:29;246290:12;246274:15;:29::i;:::-;:70;;246335:9;;;;;;;;;;;;246274:70;;;246306:26;;;-1:-1:-1;;;;;246325:5:0;3709:32:1;246306:26:0;;;3691:51:1;3664:18;246306:26:0;;;;;;;;;;;;246274:70;246249:95;;246375:12;246389:9;246364:35;;;;;;;;;:::i;:::-;;;;;;;;;;;;;246357:42;;;246022:385;;;:::o;154110:585::-;154193:4;154500:12;154514:23;154549:5;-1:-1:-1;;;;;154541:19:0;154561:4;154541:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;154499:67;;;;154584:7;:69;;;;-1:-1:-1;154596:17:0;;:22;;:56;;;154633:10;154622:30;;;;;;;;;;;;:::i;:::-;154584:103;;;;-1:-1:-1;;;;;;;;;;154657:26:0;;:30;;;154110:585::o;78832:4292::-;78914:14;;;-1:-1:-1;;79459:1:0;79456;79449:20;79503:1;79500;79496:9;79487:18;;79559:5;79555:2;79552:13;79544:5;79540:2;79536:14;79532:34;79523:43;;;79665:5;79674:1;79665:10;79661:373;;80007:11;79999:5;:19;;;;;:::i;:::-;;79992:26;;;;;;79661:373;80161:5;80147:11;:19;80139:53;;;;-1:-1:-1;;;80139:53:0;;26479:2:1;80139:53:0;;;26461:21:1;26518:2;26498:18;;;26491:30;-1:-1:-1;;;26537:18:1;;;26530:51;26598:18;;80139:53:0;26277:345:1;80139:53:0;80455:17;80593:11;80590:1;80587;80580:25;82000:1;81152;81137:12;;:16;;81122:32;;81260:22;;;;81981:1;:15;;81980:21;;82237;;;82233:25;;82222:36;82307:21;;;82303:25;;82292:36;82378:21;;;82374:25;;82363:36;82449:21;;;82445:25;;82434:36;82520:21;;;82516:25;;82505:36;82592:21;;;82588:25;;;82577:36;;;81107:12;81511;;;81507:23;;;81503:31;;;80710:20;;;80699:32;;;81627:12;;;;80758:21;;81361:16;;;;81618:21;;;;83062:15;;;-1:-1:-1;;;;78832:4292:0:o;101384:131::-;101451:4;101475:32;101480:3;101500:5;101475:4;:32::i;101691:137::-;101761:4;101785:35;101793:3;101813:5;101785:7;:35::i;16992:398::-;17091:12;17144:5;17120:21;:29;17116:110;;;17173:41;;-1:-1:-1;;;17173:41:0;;17208:4;17173:41;;;3691:51:1;3664:18;;17173:41:0;3545:203:1;17116:110:0;17237:12;17251:23;17278:6;-1:-1:-1;;;;;17278:11:0;17297:5;17304:4;17278:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17236:73;;;;17327:55;17354:6;17362:7;17371:10;17327:26;:55::i;:::-;17320:62;16992:398;-1:-1:-1;;;;;;16992:398:0:o;92553:414::-;92616:4;94746:19;;;:12;;;:19;;;;;;92633:327;;-1:-1:-1;92676:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;92859:18;;92837:19;;;:12;;;:19;;;;;;:40;;;;92892:11;;92633:327;-1:-1:-1;92943:5:0;92936:12;;93143:1420;93209:4;93348:19;;;:12;;;:19;;;;;;93384:15;;93380:1176;;93759:21;93783:14;93796:1;93783:10;:14;:::i;:::-;93832:18;;93759:38;;-1:-1:-1;93812:17:0;;93832:22;;93853:1;;93832:22;:::i;:::-;93812:42;;93888:13;93875:9;:26;93871:405;;93922:17;93942:3;:11;;93954:9;93942:22;;;;;;;;:::i;:::-;;;;;;;;;93922:42;;94096:9;94067:3;:11;;94079:13;94067:26;;;;;;;;:::i;:::-;;;;;;;;;;;;:38;;;;94181:23;;;:12;;;:23;;;;;:36;;;93871:405;94357:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;94452:3;:12;;:19;94465:5;94452:19;;;;;;;;;;;94445:26;;;94495:4;94488:11;;;;;;;93380:1176;94539:5;94532:12;;;;;18468:597;18616:12;18646:7;18641:417;;18670:19;18678:10;18670:7;:19::i;:::-;18641:417;;;18898:17;;:22;:49;;;;-1:-1:-1;;;;;;18924:18:0;;;:23;18898:49;18894:121;;;18975:24;;-1:-1:-1;;;18975:24:0;;-1:-1:-1;;;;;3709:32:1;;18975:24:0;;;3691:51:1;3664:18;;18975:24:0;3545:203:1;18894:121:0;-1:-1:-1;19036:10:0;19029:17;;19618:528;19751:17;;:21;19747:392;;19983:10;19977:17;20040:15;20027:10;20023:2;20019:19;20012:44;19747:392;20110:17;;-1:-1:-1;;;20110:17:0;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;14:286:1;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;167:23;;-1:-1:-1;;;;;;219:32:1;;209:43;;199:71;;266:1;263;256:12;593:131;-1:-1:-1;;;;;668:31:1;;658:42;;648:70;;714:1;711;704:12;729:247;788:6;841:2;829:9;820:7;816:23;812:32;809:52;;;857:1;854;847:12;809:52;896:9;883:23;915:31;940:5;915:31;:::i;1163:127::-;1224:10;1219:3;1215:20;1212:1;1205:31;1255:4;1252:1;1245:15;1279:4;1276:1;1269:15;1295:275;1366:2;1360:9;1431:2;1412:13;;-1:-1:-1;;1408:27:1;1396:40;;-1:-1:-1;;;;;1451:34:1;;1487:22;;;1448:62;1445:88;;;1513:18;;:::i;:::-;1549:2;1542:22;1295:275;;-1:-1:-1;1295:275:1:o;1575:183::-;1635:4;-1:-1:-1;;;;;1660:6:1;1657:30;1654:56;;;1690:18;;:::i;:::-;-1:-1:-1;1735:1:1;1731:14;1747:4;1727:25;;1575:183::o;1763:668::-;1817:5;1870:3;1863:4;1855:6;1851:17;1847:27;1837:55;;1888:1;1885;1878:12;1837:55;1924:6;1911:20;1950:4;1974:60;1990:43;2030:2;1990:43;:::i;:::-;1974:60;:::i;:::-;2056:3;2080:2;2075:3;2068:15;2108:4;2103:3;2099:14;2092:21;;2165:4;2159:2;2156:1;2152:10;2144:6;2140:23;2136:34;2122:48;;2193:3;2185:6;2182:15;2179:35;;;2210:1;2207;2200:12;2179:35;2246:4;2238:6;2234:17;2260:142;2276:6;2271:3;2268:15;2260:142;;;2342:17;;2330:30;;2380:12;;;;2293;;2260:142;;;-1:-1:-1;2420:5:1;1763:668;-1:-1:-1;;;;;;1763:668:1:o;2436:348::-;2520:6;2573:2;2561:9;2552:7;2548:23;2544:32;2541:52;;;2589:1;2586;2579:12;2541:52;2629:9;2616:23;-1:-1:-1;;;;;2654:6:1;2651:30;2648:50;;;2694:1;2691;2684:12;2648:50;2717:61;2770:7;2761:6;2750:9;2746:22;2717:61;:::i;2789:642::-;2954:2;3006:21;;;3076:13;;2979:18;;;3098:22;;;2925:4;;2954:2;3177:15;;;;3151:2;3136:18;;;2925:4;3220:185;3234:6;3231:1;3228:13;3220:185;;;3309:13;;3302:21;3295:29;3283:42;;3380:15;;;;3345:12;;;;3256:1;3249:9;3220:185;;;-1:-1:-1;3422:3:1;;2789:642;-1:-1:-1;;;;;;2789:642:1:o;4217:439::-;4270:3;4308:5;4302:12;4335:6;4330:3;4323:19;4361:4;4390;4385:3;4381:14;4374:21;;4429:4;4422:5;4418:16;4452:1;4462:169;4476:6;4473:1;4470:13;4462:169;;;4537:13;;4525:26;;4571:12;;;;4606:15;;;;4498:1;4491:9;4462:169;;;-1:-1:-1;4647:3:1;;4217:439;-1:-1:-1;;;;;4217:439:1:o;4661:465::-;4918:2;4907:9;4900:21;4881:4;4944:56;4996:2;4985:9;4981:18;4973:6;4944:56;:::i;:::-;5048:9;5040:6;5036:22;5031:2;5020:9;5016:18;5009:50;5076:44;5113:6;5105;5076:44;:::i;5131:180::-;5190:6;5243:2;5231:9;5222:7;5218:23;5214:32;5211:52;;;5259:1;5256;5249:12;5211:52;-1:-1:-1;5282:23:1;;5131:180;-1:-1:-1;5131:180:1:o;5316:250::-;5401:1;5411:113;5425:6;5422:1;5419:13;5411:113;;;5501:11;;;5495:18;5482:11;;;5475:39;5447:2;5440:10;5411:113;;;-1:-1:-1;;5558:1:1;5540:16;;5533:27;5316:250::o;5571:270::-;5612:3;5650:5;5644:12;5677:6;5672:3;5665:19;5693:76;5762:6;5755:4;5750:3;5746:14;5739:4;5732:5;5728:16;5693:76;:::i;:::-;5823:2;5802:15;-1:-1:-1;;5798:29:1;5789:39;;;;5830:4;5785:50;;5571:270;-1:-1:-1;;5571:270:1:o;5846:298::-;6029:6;6022:14;6015:22;6004:9;5997:41;6074:2;6069;6058:9;6054:18;6047:30;5978:4;6094:44;6134:2;6123:9;6119:18;6111:6;6094:44;:::i;6149:276::-;6207:6;6260:2;6248:9;6239:7;6235:23;6231:32;6228:52;;;6276:1;6273;6266:12;6228:52;6315:9;6302:23;6365:10;6358:5;6354:22;6347:5;6344:33;6334:61;;6391:1;6388;6381:12;6635:393;6727:6;6780:2;6768:9;6759:7;6755:23;6751:32;6748:52;;;6796:1;6793;6786:12;6748:52;6836:9;6823:23;-1:-1:-1;;;;;6861:6:1;6858:30;6855:50;;;6901:1;6898;6891:12;6855:50;6924:22;;6980:3;6962:16;;;6958:26;6955:46;;;6997:1;6994;6987:12;7033:367;7096:8;7106:6;7160:3;7153:4;7145:6;7141:17;7137:27;7127:55;;7178:1;7175;7168:12;7127:55;-1:-1:-1;7201:20:1;;-1:-1:-1;;;;;7233:30:1;;7230:50;;;7276:1;7273;7266:12;7230:50;7313:4;7305:6;7301:17;7289:29;;7373:3;7366:4;7356:6;7353:1;7349:14;7341:6;7337:27;7333:38;7330:47;7327:67;;;7390:1;7387;7380:12;7327:67;7033:367;;;;;:::o;7405:347::-;7456:8;7466:6;7520:3;7513:4;7505:6;7501:17;7497:27;7487:55;;7538:1;7535;7528:12;7487:55;-1:-1:-1;7561:20:1;;-1:-1:-1;;;;;7593:30:1;;7590:50;;;7636:1;7633;7626:12;7590:50;7673:4;7665:6;7661:17;7649:29;;7725:3;7718:4;7709:6;7701;7697:19;7693:30;7690:39;7687:59;;;7742:1;7739;7732:12;7757:1338;7917:6;7925;7933;7941;7949;7957;7965;7973;8026:3;8014:9;8005:7;8001:23;7997:33;7994:53;;;8043:1;8040;8033:12;7994:53;8082:9;8069:23;8101:31;8126:5;8101:31;:::i;:::-;8151:5;-1:-1:-1;8208:2:1;8193:18;;8180:32;8221:33;8180:32;8221:33;:::i;:::-;8273:7;-1:-1:-1;8331:2:1;8316:18;;8303:32;-1:-1:-1;;;;;8384:14:1;;;8381:34;;;8411:1;8408;8401:12;8381:34;8450:70;8512:7;8503:6;8492:9;8488:22;8450:70;:::i;:::-;8539:8;;-1:-1:-1;8424:96:1;-1:-1:-1;8627:2:1;8612:18;;8599:32;;-1:-1:-1;8643:16:1;;;8640:36;;;8672:1;8669;8662:12;8640:36;8711:72;8775:7;8764:8;8753:9;8749:24;8711:72;:::i;:::-;8802:8;;-1:-1:-1;8685:98:1;-1:-1:-1;8890:3:1;8875:19;;8862:33;;-1:-1:-1;8907:16:1;;;8904:36;;;8936:1;8933;8926:12;8904:36;;8975:60;9027:7;9016:8;9005:9;9001:24;8975:60;:::i;:::-;7757:1338;;;;-1:-1:-1;7757:1338:1;;-1:-1:-1;7757:1338:1;;;;;;9054:8;-1:-1:-1;;;7757:1338:1:o;9307:118::-;9393:5;9386:13;9379:21;9372:5;9369:32;9359:60;;9415:1;9412;9405:12;9430:1207;9545:6;9553;9606:2;9594:9;9585:7;9581:23;9577:32;9574:52;;;9622:1;9619;9612:12;9574:52;9662:9;9649:23;-1:-1:-1;;;;;9732:2:1;9724:6;9721:14;9718:34;;;9748:1;9745;9738:12;9718:34;9771:61;9824:7;9815:6;9804:9;9800:22;9771:61;:::i;:::-;9761:71;;9851:2;9841:12;;9906:2;9895:9;9891:18;9878:32;9935:2;9925:8;9922:16;9919:36;;;9951:1;9948;9941:12;9919:36;9974:24;;;-1:-1:-1;10029:4:1;10021:13;;10017:27;-1:-1:-1;10007:55:1;;10058:1;10055;10048:12;10007:55;10094:2;10081:16;10117:60;10133:43;10173:2;10133:43;:::i;10117:60::-;10211:15;;;10293:1;10289:10;;;;10281:19;;10277:28;;;10242:12;;;;10317:19;;;10314:39;;;10349:1;10346;10339:12;10314:39;10373:11;;;;10393:214;10409:6;10404:3;10401:15;10393:214;;;10489:3;10476:17;10506:28;10528:5;10506:28;:::i;:::-;10547:18;;10426:12;;;;10585;;;;10393:214;;;10626:5;10616:15;;;;;;;9430:1207;;;;;:::o;10839:261::-;11018:2;11007:9;11000:21;10981:4;11038:56;11090:2;11079:9;11075:18;11067:6;11038:56;:::i;11105:823::-;11211:6;11219;11227;11235;11243;11251;11304:3;11292:9;11283:7;11279:23;11275:33;11272:53;;;11321:1;11318;11311:12;11272:53;11360:9;11347:23;11379:31;11404:5;11379:31;:::i;:::-;11429:5;-1:-1:-1;11486:2:1;11471:18;;11458:32;11499:33;11458:32;11499:33;:::i;:::-;11551:7;-1:-1:-1;11605:2:1;11590:18;;11577:32;;-1:-1:-1;11656:2:1;11641:18;;11628:32;;-1:-1:-1;11711:3:1;11696:19;;11683:33;-1:-1:-1;;;;;11728:30:1;;11725:50;;;11771:1;11768;11761:12;11725:50;11810:58;11860:7;11851:6;11840:9;11836:22;11810:58;:::i;:::-;11105:823;;;;-1:-1:-1;11105:823:1;;-1:-1:-1;11105:823:1;;11887:8;;11105:823;-1:-1:-1;;;11105:823:1:o;11933:127::-;11994:10;11989:3;11985:20;11982:1;11975:31;12025:4;12022:1;12015:15;12049:4;12046:1;12039:15;12247:251;12317:6;12370:2;12358:9;12349:7;12345:23;12341:32;12338:52;;;12386:1;12383;12376:12;12338:52;12418:9;12412:16;12437:31;12462:5;12437:31;:::i;12503:184::-;12573:6;12626:2;12614:9;12605:7;12601:23;12597:32;12594:52;;;12642:1;12639;12632:12;12594:52;-1:-1:-1;12665:16:1;;12503:184;-1:-1:-1;12503:184:1:o;12692:127::-;12753:10;12748:3;12744:20;12741:1;12734:31;12784:4;12781:1;12774:15;12808:4;12805:1;12798:15;12824:128;12891:9;;;12912:11;;;12909:37;;;12926:18;;:::i;12957:545::-;13050:4;13056:6;13116:11;13103:25;13210:2;13206:7;13195:8;13179:14;13175:29;13171:43;13151:18;13147:68;13137:96;;13229:1;13226;13219:12;13137:96;13256:33;;13308:20;;;-1:-1:-1;;;;;;13340:30:1;;13337:50;;;13383:1;13380;13373:12;13337:50;13416:4;13404:17;;-1:-1:-1;13467:1:1;13463:14;;;13447;13443:35;13433:46;;13430:66;;;13492:1;13489;13482:12;13507:135;13546:3;13567:17;;;13564:43;;13587:18;;:::i;:::-;-1:-1:-1;13634:1:1;13623:13;;13507:135::o;13647:1532::-;13874:2;13863:9;13856:21;13837:4;13912:6;13906:13;13938:6;13980:2;13975;13964:9;13960:18;13953:30;14006:63;14064:3;14053:9;14049:19;14035:12;14006:63;:::i;:::-;13992:77;;14118:2;14110:6;14106:15;14100:22;14145:2;14141:7;14212:2;14200:9;14192:6;14188:22;14184:31;14179:2;14168:9;14164:18;14157:59;14239:52;14284:6;14268:14;14239:52;:::i;:::-;14225:66;;14345:2;14337:6;14333:15;14327:22;14322:2;14311:9;14307:18;14300:50;14405:2;14397:6;14393:15;14387:22;14381:3;14370:9;14366:19;14359:51;14465:3;14457:6;14453:16;14447:23;14441:3;14430:9;14426:19;14419:52;14520:3;14512:6;14508:16;14502:23;14480:45;;14534:55;14584:3;14573:9;14569:19;14553:14;-1:-1:-1;;;;;3502:31:1;3490:44;;3436:104;14534:55;14644:3;14636:6;14632:16;14626:23;14620:3;14609:9;14605:19;14598:52;14699:3;14691:6;14687:16;14681:23;14659:45;;14723:3;14735:54;14785:2;14774:9;14770:18;14754:14;-1:-1:-1;;;;;3502:31:1;3490:44;;3436:104;14735:54;14838:2;14830:6;14826:15;14820:22;14798:44;;;14861:3;14928:2;14916:9;14908:6;14904:22;14900:31;14895:2;14884:9;14880:18;14873:59;14955:40;14988:6;14972:14;14955:40;:::i;:::-;15032:15;;;15026:22;15088;;;15084:31;;;15064:18;;;15057:59;14941:54;-1:-1:-1;15026:22:1;-1:-1:-1;15133:40:1;14941:54;15026:22;15133:40;:::i;15796:639::-;15849:3;15893:5;15887:12;15920:4;15915:3;15908:17;15946:46;15986:4;15981:3;15977:14;15963:12;15946:46;:::i;:::-;15934:58;;16040:4;16033:5;16029:16;16023:23;16082:1;16078;16073:3;16069:11;16065:19;16136:2;16120:14;16116:23;16109:4;16104:3;16100:14;16093:47;16201:2;16193:4;16186:5;16182:16;16176:23;16172:32;16165:4;16160:3;16156:14;16149:56;;;16266:4;16258;16251:5;16247:16;16241:23;16237:34;16230:4;16225:3;16221:14;16214:58;-1:-1:-1;;;;;16325:4:1;16318:5;16314:16;16308:23;16304:48;16297:4;16292:3;16288:14;16281:72;16402:4;16395:5;16391:16;16385:23;16378:4;16373:3;16369:14;16362:47;16425:4;16418:11;;;15796:639;;;;:::o;16440:1736::-;16667:2;16656:9;16649:21;16630:4;16705:6;16699:13;16748:2;16743;16732:9;16728:18;16721:30;16793:12;16787:19;16782:2;16771:9;16767:18;16760:47;16867:2;16853:12;16849:21;16843:28;16838:2;16827:9;16823:18;16816:56;16933:2;16919:12;16915:21;16909:28;16903:3;16892:9;16888:19;16881:57;16999:2;16985:12;16981:21;16975:28;16969:3;16958:9;16954:19;16947:57;17059:3;17045:12;17041:22;17035:29;17083:6;17126:2;17120:3;17109:9;17105:19;17098:31;17152:65;17212:3;17201:9;17197:19;17181:14;17152:65;:::i;:::-;17138:79;;17272:3;17258:12;17254:22;17248:29;17300:2;17296:7;17368:2;17356:9;17348:6;17344:22;17340:31;17334:3;17323:9;17319:19;17312:60;17395:40;17428:6;17412:14;17395:40;:::i;:::-;17381:54;;17490:3;17476:12;17472:22;17466:29;17444:51;;17514:3;17526:51;17573:2;17562:9;17558:18;17542:14;375:13;368:21;356:34;;305:91;17526:51;17632:3;17618:12;17614:22;17608:29;17586:51;;17656:3;17668:51;17715:2;17704:9;17700:18;17684:14;375:13;368:21;356:34;;305:91;17668:51;17756:21;;;17750:28;;-1:-1:-1;17797:3:1;;17809:54;17844:18;;;17750:28;-1:-1:-1;;;;;3502:31:1;3490:44;;3436:104;17809:54;17900:21;;17894:28;-1:-1:-1;;;;;3502:31:1;17966:18;;;3490:44;;;;18022:21;;;;18016:28;18085:22;;;18081:31;;;18075:3;18060:19;;18053:60;18016:28;-1:-1:-1;18130:40:1;18085:22;18016:28;18130:40;:::i;18181:620::-;18244:3;18275;18307:5;18301:12;18334:6;18329:3;18322:19;18360:4;18389;18384:3;18380:14;18373:21;;18447:4;18437:6;18434:1;18430:14;18423:5;18419:26;18415:37;18486:4;18479:5;18475:16;18509:1;18519:256;18533:6;18530:1;18527:13;18519:256;;;18620:2;18616:7;18608:5;18602:4;18598:16;18594:30;18589:3;18582:43;18646:49;18690:4;18681:6;18675:13;18646:49;:::i;:::-;18753:12;;;;18638:57;-1:-1:-1;18718:15:1;;;;18555:1;18548:9;18519:256;;;-1:-1:-1;18791:4:1;;18181:620;-1:-1:-1;;;;;;;18181:620:1:o;18806:452::-;18856:3;18894:5;18888:12;18921:6;18916:3;18909:19;18947:4;18976;18971:3;18967:14;18960:21;;19015:4;19008:5;19004:16;19038:1;19048:185;19062:6;19059:1;19056:13;19048:185;;;19137:13;;19130:21;19123:29;19111:42;;19173:12;;;;19208:15;;;;19084:1;19077:9;19048:185;;19263:2456;19488:2;19477:9;19470:21;19451:4;19526:6;19520:13;19569:2;19564;19553:9;19549:18;19542:30;19609:12;19603:19;19641:6;19683:2;19678;19667:9;19663:18;19656:30;19709:65;19769:3;19758:9;19754:19;19738:14;19709:65;:::i;:::-;19695:79;;19829:2;19815:12;19811:21;19805:28;19856:2;19852:7;19923:2;19911:9;19903:6;19899:22;19895:31;19890:2;19879:9;19875:18;19868:59;19950:52;19995:6;19979:14;19950:52;:::i;:::-;19936:66;;20057:2;20043:12;20039:21;20033:28;20011:50;;20126:2;20114:9;20106:6;20102:22;20098:31;20092:3;20081:9;20077:19;20070:60;20153:52;20198:6;20182:14;20153:52;:::i;:::-;20139:66;;20260:2;20246:12;20242:21;20236:28;20214:50;;20329:2;20317:9;20309:6;20305:22;20301:31;20295:3;20284:9;20280:19;20273:60;20356:52;20401:6;20385:14;20356:52;:::i;:::-;20342:66;;20463:3;20449:12;20445:22;20439:29;20417:51;;20533:2;20521:9;20513:6;20509:22;20505:31;20499:3;20488:9;20484:19;20477:60;20560:62;20615:6;20599:14;20560:62;:::i;:::-;20546:76;;20677:3;20663:12;20659:22;20653:29;20631:51;;20747:2;20735:9;20727:6;20723:22;20719:31;20713:3;20702:9;20698:19;20691:60;20774:40;20807:6;20791:14;20774:40;:::i;:::-;20760:54;;20869:3;20855:12;20851:22;20845:29;20823:51;;20893:3;20960:2;20948:9;20940:6;20936:22;20932:31;20927:2;20916:9;20912:18;20905:59;20987:49;21029:6;21013:14;20987:49;:::i;:::-;20973:63;;21091:3;21077:12;21073:22;21067:29;21045:51;;21115:3;21182:2;21170:9;21162:6;21158:22;21154:31;21149:2;21138:9;21134:18;21127:59;21209:49;21251:6;21235:14;21209:49;:::i;:::-;21195:63;;21313:2;21299:12;21295:21;21289:28;21267:50;;21336:3;21326:13;;21348:54;21398:2;21387:9;21383:18;21367:14;-1:-1:-1;;;;;3502:31:1;3490:44;;3436:104;21724:287;21853:3;21891:6;21885:13;21907:66;21966:6;21961:3;21954:4;21946:6;21942:17;21907:66;:::i;:::-;21989:16;;;;;21724:287;-1:-1:-1;;21724:287:1:o;22016:125::-;22081:9;;;22102:10;;;22099:36;;;22115:18;;:::i;22455:562::-;-1:-1:-1;;;;;22740:32:1;;22722:51;;22809:2;22804;22789:18;;22782:30;;;-1:-1:-1;;22835:56:1;;22872:18;;22864:6;22835:56;:::i;:::-;22939:9;22931:6;22927:22;22922:2;22911:9;22907:18;22900:50;22967:44;23004:6;22996;22967:44;:::i;23022:245::-;23089:6;23142:2;23130:9;23121:7;23117:23;23113:32;23110:52;;;23158:1;23155;23148:12;23110:52;23190:9;23184:16;23209:28;23231:5;23209:28;:::i;23885:596::-;23936:3;23967;23999:5;23993:12;24026:6;24021:3;24014:19;24052:4;24081;24076:3;24072:14;24065:21;;24139:4;24129:6;24126:1;24122:14;24115:5;24111:26;24107:37;24178:4;24171:5;24167:16;24201:1;24211:244;24225:6;24222:1;24219:13;24211:244;;;24312:2;24308:7;24300:5;24294:4;24290:16;24286:30;24281:3;24274:43;24338:37;24370:4;24361:6;24355:13;24338:37;:::i;:::-;24433:12;;;;24330:45;-1:-1:-1;24398:15:1;;;;24247:1;24240:9;24211:244;;24486:348;24711:6;24700:9;24693:25;24754:2;24749;24738:9;24734:18;24727:30;24674:4;24774:54;24824:2;24813:9;24809:18;24801:6;24774:54;:::i;24839:365::-;25082:4;25074:6;25070:17;25059:9;25052:36;25124:2;25119;25108:9;25104:18;25097:30;25033:4;25144:54;25194:2;25183:9;25179:18;25171:6;25144:54;:::i;25496:127::-;25557:10;25552:3;25548:20;25545:1;25538:31;25588:4;25585:1;25578:15;25612:4;25609:1;25602:15;25628:127;25689:10;25684:3;25680:20;25677:1;25670:31;25720:4;25717:1;25710:15;25744:4;25741:1;25734:15;25760:219;25909:2;25898:9;25891:21;25872:4;25929:44;25969:2;25958:9;25954:18;25946:6;25929:44;:::i;25984:288::-;26159:6;26148:9;26141:25;26202:2;26197;26186:9;26182:18;26175:30;26122:4;26222:44;26262:2;26251:9;26247:18;26239:6;26222:44;:::i;26627:127::-;26688:10;26683:3;26679:20;26676:1;26669:31;26719:4;26716:1;26709:15;26743:4;26740:1;26733:15
Swarm Source
ipfs://84dc9ef8254b7f2d70223b44c21428352171c4b4b68adb9e9c7c089f7146953b
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 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.