More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 122 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Approve | 22313540 | 5 mins ago | IN | 0 ETH | 0.00001974 | ||||
Report | 22313045 | 1 hr ago | IN | 0 ETH | 0.00019019 | ||||
Approve | 22310282 | 11 hrs ago | IN | 0 ETH | 0.00001556 | ||||
Report | 22305731 | 26 hrs ago | IN | 0 ETH | 0.0001654 | ||||
Approve | 22304459 | 30 hrs ago | IN | 0 ETH | 0.00004081 | ||||
Redeem | 22302801 | 36 hrs ago | IN | 0 ETH | 0.00047102 | ||||
Approve | 22299076 | 2 days ago | IN | 0 ETH | 0.00004068 | ||||
Report | 22298418 | 2 days ago | IN | 0 ETH | 0.00020511 | ||||
Rebalance | 22297692 | 2 days ago | IN | 0 ETH | 0.00058434 | ||||
Approve | 22297149 | 2 days ago | IN | 0 ETH | 0.00002649 | ||||
Approve | 22296505 | 2 days ago | IN | 0 ETH | 0.00002639 | ||||
Approve | 22293275 | 2 days ago | IN | 0 ETH | 0.00002004 | ||||
Report | 22291101 | 3 days ago | IN | 0 ETH | 0.00018293 | ||||
Approve | 22288555 | 3 days ago | IN | 0 ETH | 0.0000197 | ||||
Approve | 22288545 | 3 days ago | IN | 0 ETH | 0.00001925 | ||||
Report | 22283854 | 4 days ago | IN | 0 ETH | 0.00026379 | ||||
Redeem | 22281071 | 4 days ago | IN | 0 ETH | 0.00050851 | ||||
Report | 22276612 | 5 days ago | IN | 0 ETH | 0.00026358 | ||||
Report | 22269309 | 6 days ago | IN | 0 ETH | 0.00030304 | ||||
Report | 22262107 | 7 days ago | IN | 0 ETH | 0.00027156 | ||||
Report | 22254782 | 8 days ago | IN | 0 ETH | 0.00028192 | ||||
Report | 22247458 | 9 days ago | IN | 0 ETH | 0.00131453 | ||||
Report | 22240135 | 10 days ago | IN | 0 ETH | 0.00142532 | ||||
Approve | 22237015 | 10 days ago | IN | 0 ETH | 0.00003172 | ||||
Approve | 22237014 | 10 days ago | IN | 0 ETH | 0.00005203 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0xF7DE3c70...3e217822a The constructor portion of the code might be different and could alter the actual behaviour of the contract
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"}]
Deployed Bytecode
0x6080604052600436106101e2575f3560e01c80638a4adf2411610101578063c7b9d53011610094578063d65ba11a11610063578063d65ba11a14610671578063ecf7085814610686578063f23a6e611461069b578063fde813a8146104f0576101e2565b8063c7b9d530146105d2578063ca70baa3146105f1578063d01f63f514610629578063d19a3bb81461064a576101e2565b8063b5f163ff116100d0578063b5f163ff1461052e578063bc197c811461054d578063bdc8144b14610594578063c04dad5d146105b3576101e2565b80638a4adf24146104be5780638adb2ca9146104dd5780639d7fb70c146104f0578063b543503e1461050f576101e2565b80633d6cb575116101795780635d265d3f116101485780635d265d3f146103f457806377ca76b81461043557806381cd63771461045457806385e1f4d014610473576101e2565b80633d6cb5751461038357806346aa2f12146103a257806349317f1d146103c1578063503160d9146103d5576101e2565b80631fe4a686116101b55780631fe4a686146102c557806324c73dda146102fb57806334c041a51461032e57806335ad30b514610361576101e2565b806301ffc9a71461022357806304bd46291461025757806310bc7abf1461028557806318354273146102b1575b3480156101ed575f80fd5b5073bb51273d6c746910c7c06fe718f30c936170fed0365f80375f80365f845af43d5f803e80801561021d573d5ff35b3d5ffd5b005b34801561022e575f80fd5b5061024261023d3660046145a0565b6106c7565b60405190151581526020015b60405180910390f35b348015610262575f80fd5b506102776102713660046145db565b505f1990565b60405190815260200161024e565b348015610290575f80fd5b506102a461029f3660046146c8565b6106fd565b60405161024e91906146f9565b3480156102bc575f80fd5b506102216107ae565b3480156102d0575f80fd5b505f546102e3906001600160a01b031681565b6040516001600160a01b03909116815260200161024e565b348015610306575f80fd5b506102e37f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a251481565b348015610339575f80fd5b506102e37f000000000000000000000000d85ec15a9f814d6173bf1a89273bfb3964aadaec81565b34801561036c575f80fd5b506103756108d9565b60405161024e929190614778565b34801561038e575f80fd5b5061022161039d36600461479c565b610988565b3480156103ad575f80fd5b506102776103bc3660046145db565b61099c565b3480156103cc575f80fd5b50610277610a45565b3480156103e0575f80fd5b506102216103ef36600461479c565b610a5b565b3480156103ff575f80fd5b5060408051600481526024810182526020810180516001600160e01b031663440368a360e01b179052905161024e915f91614800565b348015610440575f80fd5b5061027761044f36600461479c565b610a6c565b34801561045f575f80fd5b5061022161046e36600461481a565b610a8b565b34801561047e575f80fd5b506104a67f000000000000000000000000000000000000000000000000000000000000000181565b6040516001600160401b03909116815260200161024e565b3480156104c9575f80fd5b506001546102e3906001600160a01b031681565b6102216104eb36600461483d565b610b4a565b3480156104fb575f80fd5b5061022161050a36600461479c565b610f7a565b34801561051a575f80fd5b506102216105293660046145db565b610f82565b348015610539575f80fd5b5061027761054836600461479c565b611072565b348015610558575f80fd5b5061057b6105673660046148f7565b63bc197c8160e01b98975050505050505050565b6040516001600160e01b0319909116815260200161024e565b34801561059f575f80fd5b506102216105ae36600461479c565b611081565b3480156105be575f80fd5b506102216105cd3660046149ba565b6110e1565b3480156105dd575f80fd5b506102216105ec3660046145db565b6111a3565b3480156105fc575f80fd5b5060015461061490600160a01b900463ffffffff1681565b60405163ffffffff909116815260200161024e565b348015610634575f80fd5b5061063d611264565b60405161024e9190614a77565b348015610655575f80fd5b506102e373bb51273d6c746910c7c06fe718f30c936170fed081565b34801561067c575f80fd5b5061027760025481565b348015610691575f80fd5b5061027760035481565b3480156106a6575f80fd5b5061057b6106b5366004614a89565b63f23a6e6160e01b9695505050505050565b5f6001600160e01b031982166301ffc9a760e01b14806106f757506001600160e01b03198216630271189760e51b145b92915050565b8051606090806001600160401b0381111561071a5761071a6145f6565b604051908082528060200260200182016040528015610743578160200160208202803683370190505b5091505f5b818110156107a75761077d84828151811061076557610765614aff565b6020026020010151600461127090919063ffffffff16565b83828151811061078f5761078f614aff565b91151560209283029190910190910152600101610748565b5050919050565b6040516321f8a72160e01b81527fbddfa8c39a1f6275bcfb3aa5c70638c466999edbf14e6162d81b3492caca9fce60048201525f907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa158015610832573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108569190614b13565b90507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25f6108838261128a565b905080156108d45761089f6001600160a01b03831684836112f2565b6040518181527f76a820ad5e56aebcfa13f60a4ec2e8453550cca0e77446a259782e547c68b32b906020015b60405180910390a15b505050565b606080600660078180548060200260200160405190810160405280929190818152602001828054801561092957602002820191905f5260205f20905b815481526020019060010190808311610915575b505050505091508080548060200260200160405190810160405280929190818152602001828054801561097957602002820191905f5260205f20905b815481526020019060010190808311610965575b50505050509050915091509091565b610990611351565b6109998161138f565b50565b5f807f000000000000000000000000ef101508bf4dc6cf0f0a0c135f39a41fab4e43896001600160a01b03166301e1d1146040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109fa573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a1e9190614b2e565b60035490915080821015610a3b57610a368282614b59565b610a3d565b5f5b949350505050565b5f610a4e611351565b610a56611555565b905090565b610a63611351565b6109998161175a565b60068181548110610a7b575f80fd5b5f91825260209091200154905081565b6040516348e4a64960e01b81523360048201527f000000000000000000000000ef101508bf4dc6cf0f0a0c135f39a41fab4e43896001600160a01b0316906348e4a649906024015f6040518083038186803b158015610ae8575f80fd5b505afa158015610afa573d5f803e3d5ffd5b505050508063ffffffff165f03610b24576040516360d4aee560e11b815260040160405180910390fd5b6001805463ffffffff909216600160a01b0263ffffffff60a01b19909216919091179055565b5f546001600160a01b03163314610b74576040516312b9d85760e01b815260040160405180910390fd5b5f610b7f8280614b6c565b91505f9050610b916020840184614b6c565b91505f9050610ba36040850185614b6c565b90509050815f03610bc75760405163ec5e1a0b60e01b815260040160405180910390fd5b805f03610be757604051636e1d500960e11b815260040160405180910390fd5b8183141580610c045750610bfe6060850185614b6c565b90508114155b15610c2257604051634456f5e960e11b815260040160405180910390fd5b6002545f90815b85811015610ca2575f5b82811015610c995760068181548110610c4e57610c4e614aff565b5f91825260209091200154610c638980614b6c565b84818110610c7357610c73614aff565b9050602002013503610c915783610c8981614bb1565b945050610c99565b600101610c33565b50600101610c29565b50848214610cc35760405163173b81c360e21b815260040160405180910390fd5b50600190505b83811015610d4657610cdb8580614b6c565b610ce6600184614b59565b818110610cf557610cf5614aff565b60200291909101359050610d098680614b6c565b83818110610d1957610d19614aff565b9050602002013511610d3e5760405163ac5c256f60e01b815260040160405180910390fd5b600101610cc9565b505f5b81811015610e2f5760018110158015610db55750610d6a6040860186614b6c565b610d75600184614b59565b818110610d8457610d84614aff565b90506020020135858060400190610d9b9190614b6c565b83818110610dab57610dab614aff565b9050602002013511155b15610dd3576040516345109f5760e11b815260040160405180910390fd5b610e0a610de36040870187614b6c565b83818110610df357610df3614aff565b90506020020135600461127090919063ffffffff16565b610e275760405163d902535160e01b815260040160405180910390fd5b600101610d49565b505f610e6f610e3e8680614b6c565b610e4b6020890189614b6c565b610e5860408b018b614b6c565b610e6560608d018d614b6c565b8d608001356119f3565b90505f610e9b7fcfa3537c7b7ad87a0dd290c1d493cb256cbf491441572cd66c66c6af6310399b611c69565b9050610eaf81835f01518460200151611cf2565b604051633452c8ed60e21b81526001600160a01b0382169063d14b23b490610edb908590600401614bc9565b5f604051808303815f87803b158015610ef2575f80fd5b505af1158015610f04573d5f803e3d5ffd5b50505050610f727f00000000000000000000000001df6fb6a28a89d6bfa53b2b3f20644abf417678878060400190610f3c9190614b6c565b808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250611d7492505050565b505050505050565b610999611351565b6040516348e4a64960e01b81523360048201527f000000000000000000000000ef101508bf4dc6cf0f0a0c135f39a41fab4e43896001600160a01b0316906348e4a649906024015f6040518083038186803b158015610fdf575f80fd5b505afa158015610ff1573d5f803e3d5ffd5b5050506001600160a01b038216905061101d5760405163538ba4f960e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f8e902340d35762a5a36507c20fe38e5d549a721d9f846d6de7f397b5c26ab853906020015b60405180910390a150565b60078181548110610a7b575f80fd5b6001546001600160a01b031633146110ac57604051634f9aa11760e11b815260040160405180910390fd5b60038190556040518181527f5d2e73196f8ba1b44e887e2bcc9bcd1f3e657add341d4a0a632ffff00d6903f290602001611067565b6001546001600160a01b0316331461110c57604051634f9aa11760e11b815260040160405180910390fd5b81518151811461112f57604051634456f5e960e11b815260040160405180910390fd5b805f0361114f576040516342c313c360e11b815260040160405180910390fd5b5f5b8181101561119d5761119584828151811061116e5761116e614aff565b602002602001015184838151811061118857611188614aff565b60200260200101516122b8565b600101611151565b50505050565b6040516348e4a64960e01b81523360048201527f000000000000000000000000ef101508bf4dc6cf0f0a0c135f39a41fab4e43896001600160a01b0316906348e4a649906024015f6040518083038186803b158015611200575f80fd5b505afa158015611212573d5f803e3d5ffd5b50505f80546001600160a01b0319166001600160a01b0385169081179091556040519081527f276625620b877c2ddc0a05d68b81971639085fa26d23dfa86eec6460e6fac5b992506020019050611067565b6060610a566004612325565b5f81815260018301602052604081205415155b9392505050565b6040516370a0823160e01b81523060048201525f906001600160a01b038316906370a0823190602401602060405180830381865afa1580156112ce573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f79190614b2e565b6040516001600160a01b038381166024830152604482018390526108d491859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050612331565b33301461138d5760405162461bcd60e51b815260206004820152600560248201526410b9b2b63360d91b60448201526064015b60405180910390fd5b565b6002546060907f000000000000000000000000a195608c2306a26f727d5199d5a382a4508308da9060010361143d575f6113c884612392565b60408051602081018252828152905191925063407c7b1d60e01b916113f09190602401614d0e565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050925061143782825f015183602001516125c0565b506114b8565b5f6114478461261c565b604080516020810182528281529051919250630b0702e960e21b9161146f9190602401614e81565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b03838183161783525050505092506114b682825f01518360200151611cf2565b505b5f80826001600160a01b0316846040516114d29190614f98565b5f604051808303815f865af19150503d805f811461150b576040519150601f19603f3d011682016040523d82523d5f602084013e611510565b606091505b5091509150610f7282826040518060400160405280601a81526020017f43616c6c526576657274576974684e6f52657475726e44617461000000000000815250612d0f565b60025460068054604080516020808402820181019092528281525f948594909385938301828280156115a457602002820191905f5260205f20905b815481526020019060010190808311611590575b505050505090505f7f00000000000000000000000001df6fb6a28a89d6bfa53b2b3f20644abf41767890505f5b8381101561171d575f6115fc8483815181106115ef576115ef614aff565b6020026020010151612d28565b505090505f836001600160a01b031662fdd58e3087868151811061162257611622614aff565b60200260200101516040518363ffffffff1660e01b815260040161165b9291906001600160a01b03929092168252602082015260400190565b602060405180830381865afa158015611676573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061169a9190614b2e565b60405163b7ba28cd60e01b8152600481018290529091506001600160a01b0383169063b7ba28cd90602401602060405180830381865afa1580156116e0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117049190614b2e565b61170e9088614fb3565b965082600101925050506115d1565b506117477f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc261128a565b6117519085614fb3565b94505050505090565b5f6002546001146117ca5763fa0f64eb60e01b604051806020016040528061178185612d5b565b90526040516117939190602401614e81565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261182b565b63b19dcc3360e01b60405180602001604052806117e685613203565b90526040516117f89190602401614d0e565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091525b90507f000000000000000000000000a195608c2306a26f727d5199d5a382a4508308da6118826001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2168285613375565b5f80826001600160a01b03168460405161189c9190614f98565b5f604051808303815f865af19150503d805f81146118d5576040519150601f19603f3d011682016040523d82523d5f602084013e6118da565b606091505b509150915061191f82826040518060400160405280601a81526020017f43616c6c526576657274576974684e6f52657475726e44617461000000000000815250612d0f565b50604051636eb1769f60e11b81523060048201526001600160a01b0384811660248301525f917f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29091169063dd62ed3e90604401602060405180830381865afa15801561198e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119b29190614b2e565b11156119ec576119ec6001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc216845f6133f7565b5050505050565b611a5560405180610140016040528060608152602001606081526020015f81526020015f81526020015f81526020015f6001600160a01b031681526020015f81526020015f6001600160a01b0316815260200160608152602001606081525090565b8989808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250505090825250604080516020808a02828101820190935289825290918a918a9182918501908490808284375f9201829052506020808701959095526001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21660a087015260c086018790523060e0870152604080518f870281810188019092528f81529195869550611b8094509192508f918f9182918501908490808284375f81840152601f19601f820116905080830192505050505050508b8b808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250899250600191506134869050565b91509150632c1c0ba460e01b82604051602401611b9d9190614e81565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526101008401525f80611be38a8a8a8a6139e9565b91509150611bfc82611bf58584613bbb565b885f613486565b5060405190945063fa0f64eb60e01b90611c1a908690602401614e81565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925261012087015285019290925250919b9a5050505050505050505050565b6040516321f8a72160e01b8152600481018290525f907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa158015611cce573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f79190614b13565b6040516317ea35d960e21b81526001600160a01b037f00000000000000000000000001df6fb6a28a89d6bfa53b2b3f20644abf4176781690635fa8d76490611d4290869086908690600401614fc6565b5f604051808303815f87803b158015611d59575f80fd5b505af1158015611d6b573d5f803e3d5ffd5b50505050505050565b5f6006805480602002602001604051908101604052809291908181526020018280548015611dbf57602002820191905f5260205f20905b815481526020019060010190808311611dab575b5050835186519495509392505f9150505b82811015611e9a575f805b83811015611e2d57868181518110611df557611df5614aff565b6020026020010151868481518110611e0f57611e0f614aff565b602002602001015103611e255760019150611e2d565b600101611ddb565b5080611e9157611e5687868481518110611e4957611e49614aff565b6020026020010151613c6b565b15611e9157848281518110611e6d57611e6d614aff565b602002602001015160405163350085c960e11b815260040161138491815260200190565b50600101611dd0565b5083515f90808203611ebf576040516342c313c360e11b815260040160405180910390fd5b5f816001600160401b03811115611ed857611ed86145f6565b604051908082528060200260200182016040528015611f01578160200160208202803683370190505b5090507f000000000000000000000000d85ec15a9f814d6173bf1a89273bfb3964aadaec5f807f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2815b8681101561217557846001600160a01b031663b5c756978d8381518110611f7357611f73614aff565b60200260200101516040518263ffffffff1660e01b8152600401611f9991815260200190565b602060405180830381865afa158015611fb4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fd89190614ffb565b612012578b8181518110611fee57611fee614aff565b60200260200101516040516317ed28b560e31b815260040161138491815260200190565b6120278c82815181106115ef576115ef614aff565b90505080945050816001600160a01b0316846001600160a01b031663b60262ca6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612074573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120989190614b13565b6001600160a01b0316146120bf576040516307397cd760e01b815260040160405180910390fd5b5f6120d68e8e8481518110611e4957611e49614aff565b60405163b7ba28cd60e01b8152600481018290529091506001600160a01b0386169063b7ba28cd90602401602060405180830381865afa15801561211c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121409190614b2e565b93508387838151811061215557612155614aff565b602090810291909101015261216a848a614fb3565b985050600101611f4a565b505f805b612184600189614b59565b81101561220a576121bd6127108a5f8a85815181106121a5576121a5614aff565b6020026020010151613cd8909392919063ffffffff16565b8782815181106121cf576121cf614aff565b6020026020010181815250508681815181106121ed576121ed614aff565b6020026020010151826122009190614fb3565b9150600101612179565b5061221781612710614b59565b8661222360018a614b59565b8151811061223357612233614aff565b6020026020010181815250508560079080519060200190612255929190614433565b508b516122699060069060208f0190614433565b5060028790556040517fb60570021257b8c021f071d6b761bf920e130dbbd2c819989f690f8337253b88906122a1908e908990614778565b60405180910390a150505050505050505050505050565b5f6122c4600484611270565b9050811515811515146108d45781156122e5576122e083613d33565b6122ee565b6122ee83613d42565b6040805184815283151560208201527ff5b8e2d9dfe40944d8ee0c9b9039acd8516760f92d19ef0f6aba3e0994d7287691016108cb565b60605f61128383613d4d565b5f6123456001600160a01b03841683613da6565b905080515f141580156123695750808060200190518101906123679190614ffb565b155b156108d457604051635274afe760e01b81526001600160a01b0384166004820152602401611384565b61239a61447c565b60065f815481106123ad576123ad614aff565b5f9182526020822001548083526123c390612d28565b505090505f6123f57f00000000000000000000000001df6fb6a28a89d6bfa53b2b3f20644abf417678845f0151613c6b565b60405163b7ba28cd60e01b8152600481018290529091505f906001600160a01b0384169063b7ba28cd90602401602060405180830381865afa15801561243d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124619190614b2e565b60808501516001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21660209091015284519091505f906124a690613db3565b905080156124e45760808501516001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2166040909101525b81861061250657602085018390526124fc8183613f79565b6040860152612594565b6125108187613f79565b604086810191909152516307c080f960e01b8152600481018790526001600160a01b038516906307c080f990602401602060405180830381865afa15801561255a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061257e9190614b2e565b6020860181905283101561259457602085018390525b50506064606084015250505f60c0820181905260e0820152306101008201819052610120820152919050565b60405163524fca8b60e11b81526001600160a01b03848116600483015260248201849052604482018390527f00000000000000000000000001df6fb6a28a89d6bfa53b2b3f20644abf417678169063a49f951690606401611d42565b6126246144d6565b600254600680546040805160208084028201810190925282815292919083018282801561266e57602002820191905f5260205f20905b81548152602001906001019080831161265a575b505050918452508190506001600160401b0381111561268f5761268f6145f6565b6040519080825280602002602001820160405280156126b8578160200160208202803683370190505b506020830152806001600160401b038111156126d6576126d66145f6565b6040519080825280602002602001820160405280156126ff578160200160208202803683370190505b506060830152806001600160401b0381111561271d5761271d6145f6565b60405190808252806020026020018201604052801561275657816020015b612743614540565b81526020019060019003908161273b5790505b506080830152806001600160401b03811115612774576127746145f6565b60405190808252806020026020018201604052801561279d578160200160208202803683370190505b5060c0830181905260e0830152306101008301819052610120830152806001600160401b038111156127d1576127d16145f6565b6040519080825280602002602001820160405280156127fa578160200160208202803683370190505b5060408301527f00000000000000000000000001df6fb6a28a89d6bfa53b2b3f20644abf4176785f80836001600160401b0381111561283b5761283b6145f6565b604051908082528060200260200182016040528015612864578160200160208202803683370190505b5090505f846001600160401b03811115612880576128806145f6565b6040519080825280602002602001820160405280156128a9578160200160208202803683370190505b5090505f5b858110156129de575f6128cf885f015183815181106115ef576115ef614aff565b505090506128ec86895f01518481518110611e4957611e49614aff565b8483815181106128fe576128fe614aff565b602002602001018181525050806001600160a01b031663b7ba28cd85848151811061292b5761292b614aff565b60200260200101516040518263ffffffff1660e01b815260040161295191815260200190565b602060405180830381865afa15801561296c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129909190614b2e565b8383815181106129a2576129a2614aff565b6020026020010181815250508282815181106129c0576129c0614aff565b6020026020010151856129d39190614fb3565b9450506001016128ae565b505f5b85811015612d04577f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc287608001518281518110612a2057612a20614aff565b6020026020010151602001906001600160a01b031690816001600160a01b0316815250505f612a5d885f015183815181106115ef576115ef614aff565b505090505f612a87895f01518481518110612a7a57612a7a614aff565b6020026020010151613db3565b90508015612aeb577f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc289608001518481518110612ac657612ac6614aff565b6020026020010151604001906001600160a01b031690816001600160a01b0316815250505b858a10612b7857848381518110612b0457612b04614aff565b602002602001015189602001518481518110612b2257612b22614aff565b602002602001018181525050612b5181858581518110612b4457612b44614aff565b6020026020010151613f79565b89604001518481518110612b6757612b67614aff565b602002602001018181525050612cd7565b5f612ba460078581548110612b8f57612b8f614aff565b5f9182526020822001548d9161271090613cd8565b9050612bb08282613f79565b8a604001518581518110612bc657612bc6614aff565b60209081029190910101526040516307c080f960e01b8152600481018290526001600160a01b038416906307c080f990602401602060405180830381865afa158015612c14573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c389190614b2e565b8a602001518581518110612c4e57612c4e614aff565b602002602001018181525050858481518110612c6c57612c6c614aff565b60200260200101518a602001518581518110612c8a57612c8a614aff565b60200260200101511115612cd557858481518110612caa57612caa614aff565b60200260200101518a602001518581518110612cc857612cc8614aff565b6020026020010181815250505b505b606489606001518481518110612cef57612cef614aff565b602090810291909101015250506001016129e1565b505050505050919050565b60608315612d1e575081611283565b6112838383613f90565b8060a081901c60c082901c5f819003612d545760405163030042b760e01b815260040160405180910390fd5b9193909250565b612d636144d6565b6002546006805460408051602080840282018101909252828152929190830182828015612dad57602002820191905f5260205f20905b815481526020019060010190808311612d99575b505050918452508190506001600160401b03811115612dce57612dce6145f6565b604051908082528060200260200182016040528015612df7578160200160208202803683370190505b506020830152806001600160401b03811115612e1557612e156145f6565b604051908082528060200260200182016040528015612e3e578160200160208202803683370190505b506060830152806001600160401b03811115612e5c57612e5c6145f6565b604051908082528060200260200182016040528015612e9557816020015b612e82614540565b815260200190600190039081612e7a5790505b506080830152806001600160401b03811115612eb357612eb36145f6565b604051908082528060200260200182016040528015612edc578160200160208202803683370190505b5060c0830181905260e0830152306101008301819052610120830152806001600160401b03811115612f1057612f106145f6565b604051908082528060200260200182016040528015612f39578160200160208202803683370190505b5060408301525f816001600160401b03811115612f5857612f586145f6565b604051908082528060200260200182016040528015612f8b57816020015b6060815260200190600190039081612f765790505b5090505f6007805480602002602001604051908101604052809291908181526020018280548015612fd957602002820191905f5260205f20905b815481526020019060010190808311612fc5575b505050505090505f5b838110156131d0577f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28560800151828151811061302157613021614aff565b6020026020010151602001906001600160a01b031690816001600160a01b0316815250505f61305e865f015183815181106115ef576115ef614aff565b50509050613087865f0151838151811061307a5761307a614aff565b6020026020010151613fba565b84838151811061309957613099614aff565b60200260200101819052506130d68383815181106130b9576130b9614aff565b60200260200101516127105f8a613cd8909392919063ffffffff16565b866020015183815181106130ec576130ec614aff565b602002602001018181525050806001600160a01b03166307c080f98760200151848151811061311d5761311d614aff565b60200260200101516040518263ffffffff1660e01b815260040161314391815260200190565b602060405180830381865afa15801561315e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131829190614b2e565b8660400151838151811061319857613198614aff565b6020026020010181815250506064866060015183815181106131bc576131bc614aff565b602090810291909101015250600101612fe2565b5082826040516020016131e4929190615061565b60408051601f1981840301815291905261014085015250919392505050565b61320b61447c565b60065f8154811061321e5761321e614aff565b5f91825260208083209091015483528281018490526064606084015260808301516001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21691015260c0820181905260e08201819052306101008301819052610120830152815161329490612d28565b50506040516307c080f960e01b8152600481018590529091506001600160a01b038216906307c080f990602401602060405180830381865afa1580156132dc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906133009190614b2e565b604083015281515f9061331290613fba565b6040805160018082528183019092529192505f9190816020015b606081526020019060019003908161332c57905050905081815f8151811061335657613356614aff565b60200260200101819052506001816040516020016131e4929190615079565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301525f919085169063dd62ed3e90604401602060405180830381865afa1580156133c2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906133e69190614b2e565b905061119d84846133f78585614fb3565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052613448848261404e565b61119d576040516001600160a01b0384811660248301525f604483015261347c91869182169063095ea7b39060640161131f565b61119d8482612331565b61348e614574565b5f6134976144d6565b868152602081018690525f6134cb7fcfa3537c7b7ad87a0dd290c1d493cb256cbf491441572cd66c66c6af6310399b611c69565b8851909150806001600160401b038111156134e8576134e86145f6565b604051908082528060200260200182016040528015613511578160200160208202803683370190505b506040840152806001600160401b0381111561352f5761352f6145f6565b604051908082528060200260200182016040528015613558578160200160208202803683370190505b506060840152806001600160401b03811115613576576135766145f6565b6040519080825280602002602001820160405280156135af57816020015b61359c614540565b8152602001906001900390816135945790505b5060808401525f816001600160401b038111156135ce576135ce6145f6565b60405190808252806020026020018201604052801561360157816020015b60608152602001906001900390816135ec5790505b5090505f5b82811015613944575f6136248c83815181106115ef576115ef614aff565b505090508815613764575f6136448d8481518110612a7a57612a7a614aff565b905080156136a8577f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28760800151848151811061368357613683614aff565b6020026020010151604001906001600160a01b031690816001600160a01b0316815250505b5f826001600160a01b031663b7ba28cd8e86815181106136ca576136ca614aff565b60200260200101516040518263ffffffff1660e01b81526004016136f091815260200190565b602060405180830381865afa15801561370b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061372f9190614b2e565b905061373b8282613f79565b8860400151858151811061375157613751614aff565b602002602001018181525050505061383f565b6137798c838151811061307a5761307a614aff565b83838151811061378b5761378b614aff565b6020026020010181905250806001600160a01b03166307c080f98c84815181106137b7576137b7614aff565b60200260200101516040518263ffffffff1660e01b81526004016137dd91815260200190565b602060405180830381865afa1580156137f8573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061381c9190614b2e565b8660400151838151811061383257613832614aff565b6020026020010181815250505b8560400151828151811061385557613855614aff565b6020026020010151876138689190614fb3565b9650898660600151838151811061388157613881614aff565b6020026020010181815250507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2866080015183815181106138c4576138c4614aff565b6020026020010151602001906001600160a01b031690816001600160a01b0316815250507f00000000000000000000000000000000000000000000000000000000000000018660800151838151811061391f5761391f614aff565b60209081029190910101516001600160401b0390911660809091015250600101613606565b50816001600160401b0381111561395d5761395d6145f6565b604051908082528060200260200182016040528015613986578160200160208202803683370190505b5060c0850181905260e08501526001600160a01b03831661010085015230610120850152866139d95781816040516020016139c2929190615061565b60408051601f198184030181529190526101408501525b5050508252909590945092505050565b6060805f83815b81811015613a2d57868682818110613a0a57613a0a614aff565b905060200201355f14613a255782613a2181614bb1565b9350505b6001016139f0565b50816001600160401b03811115613a4657613a466145f6565b604051908082528060200260200182016040528015613a6f578160200160208202803683370190505b509350816001600160401b03811115613a8a57613a8a6145f6565b604051908082528060200260200182016040528015613ab3578160200160208202803683370190505b5092505f805f5b83811015613b8b57888882818110613ad457613ad4614aff565b905060200201355f14613b83578a8a82818110613af357613af3614aff565b90506020020135878481518110613b0c57613b0c614aff565b602002602001018181525050888882818110613b2a57613b2a614aff565b90506020020135868481518110613b4357613b43614aff565b602002602001018181525050888882818110613b6157613b61614aff565b9050602002013582613b739190614fb3565b915082613b7f81614bb1565b9350505b600101613aba565b506127108114613bae576040516314ccf61760e31b815260040160405180910390fd5b5050505094509492505050565b606081516001600160401b03811115613bd657613bd66145f6565b604051908082528060200260200182016040528015613bff578160200160208202803683370190505b5090505f5b8251811015613c6457613c3f838281518110613c2257613c22614aff565b60200260200101516127105f87613cd8909392919063ffffffff16565b828281518110613c5157613c51614aff565b6020908102919091010152600101613c04565b5092915050565b604051627eeac760e11b8152306004820152602481018290525f906001600160a01b0384169062fdd58e90604401602060405180830381865afa158015613cb4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112839190614b2e565b5f80613ce58686866140eb565b90506001836002811115613cfb57613cfb615094565b148015613d1757505f8480613d1257613d126150a8565b868809115b15613d2a57613d27600182614fb3565b90505b95945050505050565b613d3e6004826141d0565b5050565b613d3e6004826141db565b6060815f01805480602002602001604051908101604052809291908181526020018280548015613d9a57602002820191905f5260205f20905b815481526020019060010190808311613d86575b50505050509050919050565b606061128383835f6141e6565b600154604051632ece023360e21b8152600160a01b90910463ffffffff1660048201525f907f000000000000000000000000d85ec15a9f814d6173bf1a89273bfb3964aadaec9082906001600160a01b0383169063bb3808cc90602401602060405180830381865afa158015613e2b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613e4f9190614b13565b90505f613e5b85612d28565b505090505f836001600160a01b031663b85225bb84846001600160a01b03166365cacaa46040518163ffffffff1660e01b8152600401602060405180830381865afa158015613eac573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613ed09190614b13565b604080516001600160a01b0393841660208201529290911690820152606001604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401613f2391815260200190565b602060405180830381865afa158015613f3e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613f629190614b2e565b9050858103613f7057600194505b50505050919050565b5f82613f855781611283565b611283600a83614b59565b815115613fa05781518083602001fd5b8060405162461bcd60e51b815260040161138491906150bc565b60605f613fc683613db3565b613fde5760405180602001604052805f815250614022565b604080516001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2166020820152016040516020818303038152906040525b905082816040516020016140379291906150ce565b604051602081830303815290604052915050919050565b5f805f846001600160a01b0316846040516140699190614f98565b5f604051808303815f865af19150503d805f81146140a2576040519150601f19603f3d011682016040523d82523d5f602084013e6140a7565b606091505b50915091508180156140d15750805115806140d15750808060200190518101906140d19190614ffb565b8015613d2a5750505050506001600160a01b03163b151590565b5f80805f19858709858702925082811083820303915050805f0361412257838281614118576141186150a8565b0492505050611283565b8084116141695760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b6044820152606401611384565b5f8486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091025f889003889004909101858311909403939093029303949094049190911702949350505050565b5f611283838361427f565b5f61128383836142cb565b60608147101561420b5760405163cd78605960e01b8152306004820152602401611384565b5f80856001600160a01b031684866040516142269190614f98565b5f6040518083038185875af1925050503d805f8114614260576040519150601f19603f3d011682016040523d82523d5f602084013e614265565b606091505b50915091506142758683836143ae565b9695505050505050565b5f8181526001830160205260408120546142c457508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556106f7565b505f6106f7565b5f81815260018301602052604081205480156143a5575f6142ed600183614b59565b85549091505f9061430090600190614b59565b905081811461435f575f865f01828154811061431e5761431e614aff565b905f5260205f200154905080875f01848154811061433e5761433e614aff565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080614370576143706150e6565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506106f7565b5f9150506106f7565b6060826143c3576143be8261440a565b611283565b81511580156143da57506001600160a01b0384163b155b1561440357604051639996b31560e01b81526001600160a01b0385166004820152602401611384565b5080611283565b80511561441a5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b828054828255905f5260205f2090810192821561446c579160200282015b8281111561446c578251825591602001919060010190614451565b5061447892915061458c565b5090565b6040518061016001604052805f81526020015f81526020015f81526020015f81526020016144a8614540565b81526060602082018190525f604083018190528183018190526080830181905260a083015260c09091015290565b60405180610160016040528060608152602001606081526020016060815260200160608152602001606081526020016060815260200160608152602001606081526020015f6001600160a01b031681526020015f6001600160a01b03168152602001606081525090565b6040805160c08101825260608082525f6020830181905292820183905281018290526080810182905260a081019190915290565b60405180602001604052806145876144d6565b905290565b5b80821115614478575f815560010161458d565b5f602082840312156145b0575f80fd5b81356001600160e01b031981168114611283575f80fd5b6001600160a01b0381168114610999575f80fd5b5f602082840312156145eb575f80fd5b8135611283816145c7565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715614632576146326145f6565b604052919050565b5f6001600160401b03821115614652576146526145f6565b5060051b60200190565b5f82601f83011261466b575f80fd5b8135602061468061467b8361463a565b61460a565b8083825260208201915060208460051b8701019350868411156146a1575f80fd5b602086015b848110156146bd57803583529183019183016146a6565b509695505050505050565b5f602082840312156146d8575f80fd5b81356001600160401b038111156146ed575f80fd5b610a3d8482850161465c565b602080825282518282018190525f9190848201906040850190845b81811015614732578351151583529284019291840191600101614714565b50909695505050505050565b5f815180845260208085019450602084015f5b8381101561476d57815187529582019590820190600101614751565b509495945050505050565b604081525f61478a604083018561473e565b8281036020840152613d2a818561473e565b5f602082840312156147ac575f80fd5b5035919050565b5f5b838110156147cd5781810151838201526020016147b5565b50505f910152565b5f81518084526147ec8160208601602086016147b3565b601f01601f19169290920160200192915050565b8215158152604060208201525f610a3d60408301846147d5565b5f6020828403121561482a575f80fd5b813563ffffffff81168114611283575f80fd5b5f6020828403121561484d575f80fd5b81356001600160401b03811115614862575f80fd5b820160a08185031215611283575f80fd5b5f8083601f840112614883575f80fd5b5081356001600160401b03811115614899575f80fd5b6020830191508360208260051b85010111156148b3575f80fd5b9250929050565b5f8083601f8401126148ca575f80fd5b5081356001600160401b038111156148e0575f80fd5b6020830191508360208285010111156148b3575f80fd5b5f805f805f805f8060a0898b03121561490e575f80fd5b8835614919816145c7565b97506020890135614929816145c7565b965060408901356001600160401b0380821115614944575f80fd5b6149508c838d01614873565b909850965060608b0135915080821115614968575f80fd5b6149748c838d01614873565b909650945060808b013591508082111561498c575f80fd5b506149998b828c016148ba565b999c989b5096995094979396929594505050565b8015158114610999575f80fd5b5f80604083850312156149cb575f80fd5b82356001600160401b03808211156149e1575f80fd5b6149ed8683870161465c565b9350602091508185013581811115614a03575f80fd5b85019050601f81018613614a15575f80fd5b8035614a2361467b8261463a565b81815260059190911b82018301908381019088831115614a41575f80fd5b928401925b82841015614a68578335614a59816149ad565b82529284019290840190614a46565b80955050505050509250929050565b602081525f611283602083018461473e565b5f805f805f8060a08789031215614a9e575f80fd5b8635614aa9816145c7565b95506020870135614ab9816145c7565b9450604087013593506060870135925060808701356001600160401b03811115614ae1575f80fd5b614aed89828a016148ba565b979a9699509497509295939492505050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215614b23575f80fd5b8151611283816145c7565b5f60208284031215614b3e575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106f7576106f7614b45565b5f808335601e19843603018112614b81575f80fd5b8301803591506001600160401b03821115614b9a575f80fd5b6020019150600581901b36038213156148b3575f80fd5b5f60018201614bc257614bc2614b45565b5060010190565b602081525f8251610140806020850152614be761016085018361473e565b91506020850151601f1980868503016040870152614c05848361473e565b93506040870151606087015260608701516080870152608087015160a087015260a08701519150614c4160c08701836001600160a01b03169052565b60c087015160e087015260e08701519150610100614c69818801846001600160a01b03169052565b80880151925050610120818786030181880152614c8685846147d5565b90880151878203909201848801529350905061427583826147d5565b5f815160c08452614cb660c08501826147d5565b9050602083015160018060a01b038082166020870152806040860151166040870152505060ff60608401511660608501526001600160401b03608084015116608085015260a083015160a08501528091505092915050565b602081525f8251602080840152805160408401526020810151606084015260408101516080840152606081015160a084015260808101516101608060c0860152614d5c6101a0860183614ca2565b915060a0830151603f19808785030160e0880152614d7a84836147d5565b935060c08501519150610100614d938189018415159052565b60e08601519250610120614daa818a018515159052565b90860151925061014090614dc8898301856001600160a01b03169052565b8601516001600160a01b03169388019390935291909301518583039091016101808601529150613d2a81836147d5565b5f8282518085526020808601955060208260051b840101602086015f5b84811015614e4357601f19868403018952614e31838351614ca2565b98840198925090830190600101614e15565b5090979650505050505050565b5f815180845260208085019450602084015f5b8381101561476d578151151587529582019590820190600101614e63565b602081525f82516020808401528051610160806040860152614ea76101a086018361473e565b91506020830151603f1980878503016060880152614ec5848361473e565b93506040850151915080878503016080880152614ee2848361473e565b935060608501519150808785030160a0880152614eff848361473e565b935060808501519150808785030160c0880152614f1c8483614df8565b935060a08501519150808785030160e0880152614f3984836147d5565b935060c08501519150610100818886030181890152614f588584614e50565b945060e086015192506101208289870301818a0152614f778685614e50565b95508187015193506101409150614dc8828a01856001600160a01b03169052565b5f8251614fa98184602087016147b3565b9190910192915050565b808201808211156106f7576106f7614b45565b6001600160a01b03841681526060602082018190525f90614fe99083018561473e565b8281036040840152614275818561473e565b5f6020828403121561500b575f80fd5b8151611283816149ad565b5f8282518085526020808601955060208260051b840101602086015f5b84811015614e4357601f1986840301895261504f8383516147d5565b98840198925090830190600101615033565b828152604060208201525f610a3d6040830184615016565b60ff83168152604060208201525f610a3d6040830184615016565b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52601260045260245ffd5b602081525f61128360208301846147d5565b828152604060208201525f610a3d60408301846147d5565b634e487b7160e01b5f52603160045260245ffdfea264697066735822122084dc9ef8254b7f2d70223b44c21428352171c4b4b68adb9e9c7c089f7146953b64736f6c63430008180033
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.