Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0.000296058798909593 ETH
Eth Value
$0.97 (@ $3,276.06/ETH)Token Holdings
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 802 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Process Payload | 20228033 | 51 mins ago | IN | 0 ETH | 0.00177664 | ||||
Process Payload | 20225631 | 8 hrs ago | IN | 0.00089422 ETH | 0.00667549 | ||||
Update Deposit P... | 20225626 | 8 hrs ago | IN | 0 ETH | 0.00142475 | ||||
Process Payload | 20225496 | 9 hrs ago | IN | 0 ETH | 0.0114255 | ||||
Update Withdraw ... | 20225491 | 9 hrs ago | IN | 0 ETH | 0.01523283 | ||||
Process Payload | 20224599 | 12 hrs ago | IN | 0.00089422 ETH | 0.00290719 | ||||
Update Deposit P... | 20224594 | 12 hrs ago | IN | 0 ETH | 0.00052309 | ||||
Process Payload | 20223976 | 14 hrs ago | IN | 0.00089422 ETH | 0.00457911 | ||||
Update Deposit P... | 20223970 | 14 hrs ago | IN | 0 ETH | 0.00036199 | ||||
Process Payload | 20222931 | 17 hrs ago | IN | 0.00089422 ETH | 0.00523119 | ||||
Update Deposit P... | 20222927 | 17 hrs ago | IN | 0 ETH | 0.00070124 | ||||
Process Payload | 20220510 | 26 hrs ago | IN | 0 ETH | 0.00049232 | ||||
Process Payload | 20220268 | 26 hrs ago | IN | 0.00089936 ETH | 0.0066611 | ||||
Update Deposit P... | 20220264 | 26 hrs ago | IN | 0 ETH | 0.00114875 | ||||
Process Payload | 20216556 | 39 hrs ago | IN | 0 ETH | 0.00265903 | ||||
Update Withdraw ... | 20216552 | 39 hrs ago | IN | 0 ETH | 0.00395932 | ||||
Finalize Rescue ... | 20216462 | 39 hrs ago | IN | 0 ETH | 0.00032692 | ||||
Process Payload | 20216130 | 40 hrs ago | IN | 0.00086516 ETH | 0.00319596 | ||||
Update Deposit P... | 20216115 | 40 hrs ago | IN | 0 ETH | 0.00052711 | ||||
Propose Rescue F... | 20215247 | 43 hrs ago | IN | 0 ETH | 0.00036449 | ||||
Update Deposit P... | 20215242 | 43 hrs ago | IN | 0 ETH | 0.00060211 | ||||
Process Payload | 20214939 | 44 hrs ago | IN | 0.00086548 ETH | 0.00533399 | ||||
Update Deposit P... | 20214924 | 44 hrs ago | IN | 0 ETH | 0.00054349 | ||||
Process Payload | 20212102 | 2 days ago | IN | 0.00086802 ETH | 0.00797426 | ||||
Update Deposit P... | 20212098 | 2 days ago | IN | 0 ETH | 0.00165541 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | Value | ||
---|---|---|---|---|---|---|
20227980 | 1 hr ago | 0.00060782 ETH | ||||
20227980 | 1 hr ago | 0.00030477 ETH | ||||
20227980 | 1 hr ago | 0.00091259 ETH | ||||
20225631 | 8 hrs ago | 0.00060782 ETH | ||||
20225631 | 8 hrs ago | 0.00028639 ETH | ||||
20224599 | 12 hrs ago | 0.00060782 ETH | ||||
20224599 | 12 hrs ago | 0.00028639 ETH | ||||
20223976 | 14 hrs ago | 0.00060782 ETH | ||||
20223976 | 14 hrs ago | 0.00028639 ETH | ||||
20222931 | 17 hrs ago | 0.00060782 ETH | ||||
20222931 | 17 hrs ago | 0.00028639 ETH | ||||
20220461 | 26 hrs ago | 0.00060782 ETH | ||||
20220461 | 26 hrs ago | 0.00028839 ETH | ||||
20220461 | 26 hrs ago | 0.00089622 ETH | ||||
20220268 | 26 hrs ago | 0.00060782 ETH | ||||
20220268 | 26 hrs ago | 0.00029153 ETH | ||||
20216130 | 40 hrs ago | 0.00060367 ETH | ||||
20216130 | 40 hrs ago | 0.00026148 ETH | ||||
20214939 | 44 hrs ago | 0.00060367 ETH | ||||
20214939 | 44 hrs ago | 0.00026157 ETH | ||||
20212102 | 2 days ago | 0.00060367 ETH | ||||
20212102 | 2 days ago | 0.00026311 ETH | ||||
20212078 | 2 days ago | 0.00060367 ETH | ||||
20212078 | 2 days ago | 0.00026434 ETH | ||||
20211063 | 2 days ago | 0.00060782 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
CoreStateRegistry
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; import { BaseStateRegistry } from "src/crosschain-data/BaseStateRegistry.sol"; import { ICoreStateRegistry } from "src/interfaces/ICoreStateRegistry.sol"; import { IBaseForm } from "src/interfaces/IBaseForm.sol"; import { IBridgeValidator } from "src/interfaces/IBridgeValidator.sol"; import { IDstSwapper } from "src/interfaces/IDstSwapper.sol"; import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; import { ISuperformFactory } from "src/interfaces/ISuperformFactory.sol"; import { ISuperPositions } from "src/interfaces/ISuperPositions.sol"; import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; import { IPaymentHelper } from "src/interfaces/IPaymentHelper.sol"; import { DataLib } from "src/libraries/DataLib.sol"; import { ProofLib } from "src/libraries/ProofLib.sol"; import { ArrayCastLib } from "src/libraries/ArrayCastLib.sol"; import { PayloadUpdaterLib } from "src/libraries/PayloadUpdaterLib.sol"; import { Error } from "src/libraries/Error.sol"; import { PayloadState, AMBMessage, InitMultiVaultData, TransactionType, CallbackType, ReturnMultiData, ReturnSingleData, InitSingleVaultData, LiqRequest } from "src/types/DataTypes.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; /// @title CoreStateRegistry /// @dev Enables communication between Superform core contracts deployed on all supported networks /// @author Zeropoint Labs contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { using SafeERC20 for IERC20; using DataLib for uint256; using ProofLib for AMBMessage; ////////////////////////////////////////////////////////////// // STATE VARIABLES // ////////////////////////////////////////////////////////////// /// @dev just stores the superformIds that failed in a specific payload id mapping(uint256 payloadId => FailedDeposit) failedDeposits; ////////////////////////////////////////////////////////////// // MODIFIERS // ////////////////////////////////////////////////////////////// modifier onlySender() override { if (msg.sender != _getAddress(keccak256("SUPERFORM_ROUTER"))) revert Error.NOT_SUPERFORM_ROUTER(); _; } ////////////////////////////////////////////////////////////// // CONSTRUCTOR // ////////////////////////////////////////////////////////////// constructor(ISuperRegistry superRegistry_) BaseStateRegistry(superRegistry_) { } ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// /// @inheritdoc ICoreStateRegistry function getFailedDeposits(uint256 payloadId_) external view override returns (uint256[] memory superformIds, uint256[] memory amounts, uint256 lastProposedTime) { FailedDeposit storage failedDeposit = failedDeposits[payloadId_]; superformIds = failedDeposit.superformIds; amounts = failedDeposit.amounts; lastProposedTime = failedDeposit.lastProposedTimestamp; } /// @inheritdoc ICoreStateRegistry function validateSlippage(uint256 finalAmount_, uint256 amount_, uint256 maxSlippage_) public view returns (bool) { // only internal transaction if (msg.sender != address(this)) { revert Error.INVALID_INTERNAL_CALL(); } return PayloadUpdaterLib.validateSlippage(finalAmount_, amount_, maxSlippage_); } ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// /// @inheritdoc ICoreStateRegistry function updateDepositPayload( uint256 payloadId_, address[] calldata finalTokens_, uint256[] calldata finalAmounts_ ) external virtual override { /// @dev validates the caller _onlyAllowedCaller(keccak256("CORE_STATE_REGISTRY_UPDATER_ROLE")); /// @dev validates the payload id _validatePayloadId(payloadId_); (uint256 prevPayloadHeader, bytes memory prevPayloadBody, bytes32 prevPayloadProof,,, uint8 isMulti,,,) = _getPayload(payloadId_); PayloadUpdaterLib.validatePayloadUpdate( prevPayloadHeader, uint8(TransactionType.DEPOSIT), payloadTracking[payloadId_], isMulti ); PayloadState finalState; if (isMulti != 0) { (prevPayloadBody, finalState) = _updateMultiDeposit(payloadId_, prevPayloadBody, finalAmounts_, finalTokens_); } else { (prevPayloadBody, finalState) = _updateSingleDeposit(payloadId_, prevPayloadBody, finalAmounts_[0], finalTokens_[0]); } /// @dev updates the payload proof _updatePayload(payloadId_, prevPayloadProof, prevPayloadBody, prevPayloadHeader, finalState); /// @dev if payload is processed at this stage then it is failing if (finalState == PayloadState.PROCESSED) { emit PayloadProcessed(payloadId_); emit FailedXChainDeposits(payloadId_); } } /// @inheritdoc ICoreStateRegistry function updateWithdrawPayload(uint256 payloadId_, bytes[] calldata txData_) external virtual override { /// @dev validates the caller _onlyAllowedCaller(keccak256("CORE_STATE_REGISTRY_UPDATER_ROLE")); /// @dev validates the payload id _validatePayloadId(payloadId_); ( uint256 prevPayloadHeader, bytes memory prevPayloadBody, bytes32 prevPayloadProof, , , uint8 isMulti, , , uint64 srcChainId ) = _getPayload(payloadId_); /// @dev validate payload update PayloadUpdaterLib.validatePayloadUpdate( prevPayloadHeader, uint8(TransactionType.WITHDRAW), payloadTracking[payloadId_], isMulti ); prevPayloadBody = _updateWithdrawPayload(prevPayloadBody, srcChainId, txData_, isMulti); /// @dev updates the payload proof _updatePayload(payloadId_, prevPayloadProof, prevPayloadBody, prevPayloadHeader, PayloadState.UPDATED); emit PayloadUpdated(payloadId_); } /// @inheritdoc BaseStateRegistry function processPayload(uint256 payloadId_) external payable virtual override { /// @dev validates the caller _onlyAllowedCaller(keccak256("CORE_STATE_REGISTRY_PROCESSOR_ROLE")); /// @dev validates the payload id _validatePayloadId(payloadId_); if (payloadTracking[payloadId_] == PayloadState.PROCESSED) { revert Error.PAYLOAD_ALREADY_PROCESSED(); } PayloadState initialState = payloadTracking[payloadId_]; /// @dev sets status as processed to prevent re-entrancy payloadTracking[payloadId_] = PayloadState.PROCESSED; ( uint256 payloadHeader_, bytes memory payloadBody_, , uint8 txType, uint8 callbackType, uint8 isMulti, , address srcSender, uint64 srcChainId ) = _getPayload(payloadId_); AMBMessage memory message_ = AMBMessage(payloadHeader_, payloadBody_); /// @dev mint superPositions for successful deposits or remint for failed withdraws if (callbackType == uint256(CallbackType.RETURN) || callbackType == uint256(CallbackType.FAIL)) { ISuperPositions superPositions = ISuperPositions(_getAddress(keccak256("SUPER_POSITIONS"))); isMulti == 1 ? superPositions.stateMultiSync(message_) : superPositions.stateSync(message_); } else if (callbackType == uint8(CallbackType.INIT)) { /// @dev for initial payload processing bytes memory returnMessage; if (txType == uint8(TransactionType.WITHDRAW)) { returnMessage = isMulti == 1 ? _multiWithdrawal(payloadId_, payloadBody_, srcSender, srcChainId) : _singleWithdrawal(payloadId_, payloadBody_, srcSender, srcChainId); } else if (txType == uint8(TransactionType.DEPOSIT)) { if (initialState != PayloadState.UPDATED) { revert Error.PAYLOAD_NOT_UPDATED(); } returnMessage = isMulti == 1 ? _multiDeposit(payloadId_, payloadBody_, srcSender, srcChainId) : _singleDeposit(payloadId_, payloadBody_, srcSender, srcChainId); } _processAck(payloadId_, srcChainId, returnMessage); } else { revert Error.INVALID_PAYLOAD_TYPE(); } emit PayloadProcessed(payloadId_); } /// @inheritdoc ICoreStateRegistry function proposeRescueFailedDeposits(uint256 payloadId_, uint256[] calldata proposedAmounts_) external override { /// @dev validates the caller _onlyAllowedCaller(keccak256("CORE_STATE_REGISTRY_RESCUER_ROLE")); /// @dev validates the payload id _validatePayloadId(payloadId_); FailedDeposit storage failedDeposits_ = failedDeposits[payloadId_]; if (failedDeposits_.superformIds.length == 0 || failedDeposits_.superformIds.length != proposedAmounts_.length) { revert Error.INVALID_RESCUE_DATA(); } if (failedDeposits_.lastProposedTimestamp != 0) { revert Error.RESCUE_ALREADY_PROPOSED(); } /// @dev should set this value to dstSwapper.failedSwap().amount for interim rescue failedDeposits[payloadId_].amounts = proposedAmounts_; failedDeposits[payloadId_].lastProposedTimestamp = block.timestamp; (,, uint8 multi,,,) = DataLib.decodeTxInfo(payloadHeader[payloadId_]); address receiverAddress; if (multi == 1) { receiverAddress = abi.decode(payloadBody[payloadId_], (InitMultiVaultData)).receiverAddress; } else { receiverAddress = abi.decode(payloadBody[payloadId_], (InitSingleVaultData)).receiverAddress; } failedDeposits[payloadId_].receiverAddress = receiverAddress; emit RescueProposed(payloadId_, failedDeposits_.superformIds, proposedAmounts_, block.timestamp); } /// @inheritdoc ICoreStateRegistry function disputeRescueFailedDeposits(uint256 payloadId_) external override { /// @dev validates the payload id _validatePayloadId(payloadId_); FailedDeposit storage failedDeposits_ = failedDeposits[payloadId_]; /// @dev the msg sender should be the refund address (or) the disputer if ( !( msg.sender == failedDeposits_.receiverAddress || _hasRole(keccak256("CORE_STATE_REGISTRY_DISPUTER_ROLE"), msg.sender) ) ) { revert Error.NOT_VALID_DISPUTER(); } /// @dev the timelock is already elapsed to dispute if ( failedDeposits_.lastProposedTimestamp == 0 || block.timestamp > failedDeposits_.lastProposedTimestamp + _getDelay() ) { revert Error.DISPUTE_TIME_ELAPSED(); } /// @dev just can reset last proposed time here, since amounts should be updated again to /// pass the lastProposedTimestamp zero check in finalize failedDeposits[payloadId_].lastProposedTimestamp = 0; emit RescueDisputed(payloadId_); } /// @inheritdoc ICoreStateRegistry /// @notice is an open function & can be executed by anyone function finalizeRescueFailedDeposits(uint256 payloadId_) external override { /// @dev validates the payload id _validatePayloadId(payloadId_); FailedDeposit storage failedDeposits_ = failedDeposits[payloadId_]; /// @dev the timelock is elapsed if ( failedDeposits_.lastProposedTimestamp == 0 || block.timestamp <= failedDeposits_.lastProposedTimestamp + _getDelay() ) { revert Error.RESCUE_LOCKED(); } /// @dev set to zero to prevent re-entrancy failedDeposits_.lastProposedTimestamp = 0; uint256 len = failedDeposits_.amounts.length; for (uint256 i; i < len; ++i) { /// @dev refunds the amount to user specified refund address if (failedDeposits_.settleFromDstSwapper[i]) { IDstSwapper(_getAddress(keccak256("DST_SWAPPER"))).processFailedTx( failedDeposits_.receiverAddress, failedDeposits_.settlementToken[i], failedDeposits_.amounts[i] ); } else { IERC20(failedDeposits_.settlementToken[i]).safeTransfer( failedDeposits_.receiverAddress, failedDeposits_.amounts[i] ); } } delete failedDeposits[payloadId_]; emit RescueFinalized(payloadId_); } ////////////////////////////////////////////////////////////// // INTERNAL FUNCTIONS // ////////////////////////////////////////////////////////////// /// @dev returns vault asset from superform function _getVaultAsset(address superform_) internal view returns (address) { return IBaseForm(superform_).getVaultAsset(); } /// @dev returns if superform is valid function _isSuperform(uint256 superformId_) internal view returns (bool) { return ISuperformFactory(_getAddress(keccak256("SUPERFORM_FACTORY"))).isSuperform(superformId_); } /// @dev returns a superformAddress function _getSuperform(uint256 superformId_) internal pure returns (address superform) { (superform,,) = superformId_.getSuperform(); } /// @dev returns if an address has a specific role function _hasRole(bytes32 id_, address addressToCheck_) internal view returns (bool) { return ISuperRBAC(_getAddress(keccak256("SUPER_RBAC"))).hasRole(id_, addressToCheck_); } /// @dev returns the registry address for id function _getStateRegistryId(address registryAddress_) internal view returns (uint8 id) { return superRegistry.getStateRegistryId(registryAddress_); } /// @dev returns the address from super registry function _getAddress(bytes32 id_) internal view returns (address) { return superRegistry.getAddress(id_); } /// @dev returns the current timelock delay function _getDelay() internal view returns (uint256) { uint256 delay = superRegistry.delay(); if (delay == 0) { revert Error.DELAY_NOT_SET(); } return delay; } function _validatePayloadId(uint256 payloadId_) internal view { if (payloadId_ > payloadsCount) { revert Error.INVALID_PAYLOAD_ID(); } } function _onlyAllowedCaller(bytes32 role_) internal view { if (!_hasRole(role_, msg.sender)) revert Error.NOT_PRIVILEGED_CALLER(role_); } /// @dev retrieves information associated with the payload and validates quorum function _getPayload(uint256 payloadId_) internal view returns ( uint256 payloadHeader_, bytes memory payloadBody_, bytes32 payloadProof, uint8 txType, uint8 callbackType, uint8 isMulti, uint8 registryId, address srcSender, uint64 srcChainId ) { payloadHeader_ = payloadHeader[payloadId_]; payloadBody_ = payloadBody[payloadId_]; payloadProof = AMBMessage(payloadHeader_, payloadBody_).computeProof(); (txType, callbackType, isMulti, registryId, srcSender, srcChainId) = payloadHeader_.decodeTxInfo(); /// @dev the number of valid proofs (quorum) must be equal or larger to the required messaging quorum if (messageQuorum[payloadProof] < _getQuorum(srcChainId)) { revert Error.INSUFFICIENT_QUORUM(); } } /// @dev helper function to update multi vault deposit payload function _updateMultiDeposit( uint256 payloadId_, bytes memory prevPayloadBody_, uint256[] calldata finalAmounts_, address[] calldata finalToken_ ) internal returns (bytes memory newPayloadBody_, PayloadState finalState_) { InitMultiVaultData memory multiVaultData = abi.decode(prevPayloadBody_, (InitMultiVaultData)); uint256 arrLen = finalAmounts_.length; /// @dev compare number of vaults to update with provided finalAmounts length if (multiVaultData.amounts.length != arrLen) { revert Error.DIFFERENT_PAYLOAD_UPDATE_AMOUNTS_LENGTH(); } uint256 validLen; for (uint256 i; i < arrLen; ++i) { if (finalAmounts_[i] == 0) { revert Error.ZERO_AMOUNT(); } /// @dev observe not consuming the second return value (multiVaultData.amounts[i],, validLen) = _updateAmount( IDstSwapper(_getAddress(keccak256("DST_SWAPPER"))), multiVaultData.hasDstSwaps[i], payloadId_, i, finalAmounts_[i], finalToken_[i], multiVaultData.superformIds[i], multiVaultData.amounts[i], multiVaultData.maxSlippages[i], validLen ); } /// @dev validLen > 0 for the cases where there was at least one deposit update that had valid slippage /// @dev (v1: passedSlippage, v2: failedSlippage, v3: passedSlippage) /// @dev final vaults: (v1, v3) / PayloadState.UPDATED /// @dev if validLen is 0 then Payload is marked as processed and can be extracted via rescue if (validLen != 0) { uint256[] memory finalSuperformIds = new uint256[](validLen); uint256[] memory finalAmounts = new uint256[](validLen); uint256[] memory outputAmounts = new uint256[](validLen); uint256[] memory maxSlippage = new uint256[](validLen); bool[] memory hasDstSwaps = new bool[](validLen); bool[] memory retain4626s = new bool[](validLen); uint256 currLen; for (uint256 i; i < arrLen; ++i) { if (multiVaultData.amounts[i] != 0) { finalSuperformIds[currLen] = multiVaultData.superformIds[i]; finalAmounts[currLen] = multiVaultData.amounts[i]; outputAmounts[currLen] = multiVaultData.outputAmounts[i]; maxSlippage[currLen] = multiVaultData.maxSlippages[i]; hasDstSwaps[currLen] = multiVaultData.hasDstSwaps[i]; retain4626s[currLen] = multiVaultData.retain4626s[i]; ++currLen; } } multiVaultData.superformIds = finalSuperformIds; multiVaultData.amounts = finalAmounts; multiVaultData.outputAmounts = outputAmounts; multiVaultData.maxSlippages = maxSlippage; multiVaultData.hasDstSwaps = hasDstSwaps; multiVaultData.retain4626s = retain4626s; finalState_ = PayloadState.UPDATED; } else { finalState_ = PayloadState.PROCESSED; } newPayloadBody_ = abi.encode(multiVaultData); } /// @dev helper function to update single vault deposit payload function _updateSingleDeposit( uint256 payloadId_, bytes memory prevPayloadBody_, uint256 finalAmount_, address finalToken_ ) internal returns (bytes memory newPayloadBody_, PayloadState finalState_) { InitSingleVaultData memory singleVaultData = abi.decode(prevPayloadBody_, (InitSingleVaultData)); if (finalAmount_ == 0) { revert Error.ZERO_AMOUNT(); } /// @dev observe not consuming the third return value (singleVaultData.amount, finalState_,) = _updateAmount( IDstSwapper(_getAddress(keccak256("DST_SWAPPER"))), singleVaultData.hasDstSwap, payloadId_, 0, finalAmount_, finalToken_, singleVaultData.superformId, singleVaultData.amount, singleVaultData.maxSlippage, 0 ); newPayloadBody_ = abi.encode(singleVaultData); } function _updateAmount( IDstSwapper dstSwapper, bool hasDstSwap_, uint256 payloadId_, uint256 index_, uint256 finalAmount_, address finalToken_, uint256 superformId_, uint256 amount_, uint256 maxSlippage_, uint256 validLen_ ) internal returns (uint256, PayloadState finalState_, uint256) { if (finalToken_ == address(0)) { revert Error.ZERO_FINAL_TOKEN(); } bool failedSwapQueued; if (hasDstSwap_) { if (dstSwapper.swappedAmount(payloadId_, index_) != finalAmount_) { (address interimToken, uint256 amount) = dstSwapper.getPostDstSwapFailureUpdatedTokenAmount(payloadId_, index_); if (amount != finalAmount_) { revert Error.INVALID_DST_SWAP_AMOUNT(); } if (interimToken != finalToken_) { revert Error.INVALID_UPDATE_FINAL_TOKEN(); } failedSwapQueued = true; failedDeposits[payloadId_].superformIds.push(superformId_); failedDeposits[payloadId_].settlementToken.push(interimToken); failedDeposits[payloadId_].settleFromDstSwapper.push(true); /// @dev sets amount to zero and will mark the payload as PROCESSED amount_ = 0; finalState_ = PayloadState.PROCESSED; } } /// @dev validate payload update /// @dev validLen may only be increased here in the case where slippage for the update is valid /// @notice we enter this if condition only if there is a valid dstSwap OR if there is just bridging to this /// contract if (!failedSwapQueued) { /// if the slippage is within allowed amount && the superform id also exists try this.validateSlippage(finalAmount_, amount_, maxSlippage_) returns (bool valid) { /// @dev in case of a valid slippage check we update the amount to finalAmount_ if (valid) { amount_ = finalAmount_; /// @dev Mark the payload as UPDATED finalState_ = PayloadState.UPDATED; } } catch { /// @dev in case of negative slippage we don't update the amount in the user request to the amount /// provided by the keeper /// @notice it remains as the original amount supplied by the user in the original state request /// @notice This means than any difference from the amount provided by the keepeer to the user supplied /// amount will be collected in this contract and remain here /// @notice we consider this to also be validSlippage = true /// @dev Mark the payload as UPDATED finalState_ = PayloadState.UPDATED; } if (!(_isSuperform(superformId_) && finalState_ == PayloadState.UPDATED)) { failedDeposits[payloadId_].superformIds.push(superformId_); address asset = _fetchAndValidateFinalToken(superformId_, finalToken_, true); /// @dev if superform is invalid, try catch will fail and asset pushed is address (0) /// @notice this means that if a user tries to game the protocol with an invalid superformId, the funds /// bridged over that failed will be stuck here /// @notice assets can still be spoofed with any vault.asset(), hence this is done via permissioned role failedDeposits[payloadId_].settlementToken.push(asset); failedDeposits[payloadId_].settleFromDstSwapper.push(false); /// @dev sets amount to zero and will mark the payload as PROCESSED (overriding the previous memory /// settings) amount_ = 0; finalState_ = PayloadState.PROCESSED; } else { _fetchAndValidateFinalToken(superformId_, finalToken_, false); ++validLen_; } } return (amount_, finalState_, validLen_); } /// @dev helper function to update multi vault withdraw payload function _updateWithdrawPayload( bytes memory prevPayloadBody_, uint64 srcChainId_, bytes[] calldata txData_, uint8 multi ) internal view returns (bytes memory) { InitMultiVaultData memory multiVaultData; InitSingleVaultData memory singleVaultData; if (multi == 1) { multiVaultData = abi.decode(prevPayloadBody_, (InitMultiVaultData)); } else { singleVaultData = abi.decode(prevPayloadBody_, (InitSingleVaultData)); multiVaultData = ArrayCastLib.castToMultiVaultData(singleVaultData); } if (multiVaultData.liqData.length != txData_.length) { revert Error.DIFFERENT_PAYLOAD_UPDATE_TX_DATA_LENGTH(); } multiVaultData = _updateTxData(txData_, multiVaultData, srcChainId_, CHAIN_ID); if (multi == 0) { singleVaultData.liqData.txData = multiVaultData.liqData[0].txData; return abi.encode(singleVaultData); } return abi.encode(multiVaultData); } /// @dev validates the incoming update data function _updateTxData( bytes[] calldata txData_, InitMultiVaultData memory multiVaultData_, uint64 srcChainId_, uint64 dstChainId_ ) internal view returns (InitMultiVaultData memory) { uint256 len = multiVaultData_.liqData.length; IBaseForm superform; for (uint256 i; i < len; ++i) { if (txData_[i].length != 0 && multiVaultData_.liqData[i].txData.length == 0) { superform = IBaseForm(_getSuperform(multiVaultData_.superformIds[i])); /// @dev for withdrawals the payload update can happen on core state registry (for normal forms) /// and also can happen in timelock state registry (for timelock form) /// @notice this check validates if the state registry is eligible to update tx data for the /// corresponding superform if (superform.getStateRegistryId() == _getStateRegistryId(address(this))) { PayloadUpdaterLib.validateLiqReq(multiVaultData_.liqData[i]); IBridgeValidator bridgeValidator = IBridgeValidator(superRegistry.getBridgeValidator(multiVaultData_.liqData[i].bridgeId)); bridgeValidator.validateTxData( IBridgeValidator.ValidateTxDataArgs( txData_[i], dstChainId_, srcChainId_, multiVaultData_.liqData[i].liqDstChainId, false, address(superform), multiVaultData_.receiverAddress, _getVaultAsset(address(superform)), address(0) ) ); if ( !PayloadUpdaterLib.validateSlippage( bridgeValidator.decodeAmountIn(txData_[i], false), superform.previewRedeemFrom(multiVaultData_.amounts[i]), multiVaultData_.maxSlippages[i] ) ) { revert Error.SLIPPAGE_OUT_OF_BOUNDS(); } multiVaultData_.liqData[i].txData = txData_[i]; } } } return multiVaultData_; } function _multiWithdrawal( uint256 payloadId_, bytes memory payload_, address srcSender_, uint64 srcChainId_ ) internal returns (bytes memory) { InitMultiVaultData memory multiVaultData = abi.decode(payload_, (InitMultiVaultData)); bool errors; uint256 len = multiVaultData.superformIds.length; address superformFactory = _getAddress(keccak256("SUPERFORM_FACTORY")); for (uint256 i; i < len; ++i) { // @dev validates if superformId exists on factory if (!ISuperformFactory(superformFactory).isSuperform(multiVaultData.superformIds[i])) { revert Error.SUPERFORM_ID_NONEXISTENT(); } /// @dev Store destination payloadId_ & index in extraFormData (tbd: 1-step flow doesnt need this) try IBaseForm(_getSuperform(multiVaultData.superformIds[i])).xChainWithdrawFromVault( InitSingleVaultData({ payloadId: multiVaultData.payloadId, superformId: multiVaultData.superformIds[i], amount: multiVaultData.amounts[i], outputAmount: multiVaultData.outputAmounts[i], maxSlippage: multiVaultData.maxSlippages[i], liqData: multiVaultData.liqData[i], hasDstSwap: false, retain4626: false, receiverAddress: multiVaultData.receiverAddress, extraFormData: abi.encode(payloadId_, i) }), srcSender_, srcChainId_ ) { /// @dev marks the indexes that don't require a callback re-mint of shares (successful /// withdraws) multiVaultData.amounts[i] = 0; } catch { /// @dev detect if there is at least one failed withdraw errors = true; } } /// @dev if at least one error happens, the shares will be re-minted for the affected superformIds if (errors) { return _multiReturnData( srcSender_, multiVaultData.payloadId, TransactionType.WITHDRAW, CallbackType.FAIL, multiVaultData.superformIds, multiVaultData.amounts ); } return ""; } function _multiDeposit( uint256 payloadId_, bytes memory payload_, address srcSender_, uint64 srcChainId_ ) internal returns (bytes memory) { InitMultiVaultData memory multiVaultData = abi.decode(payload_, (InitMultiVaultData)); address[] memory superforms = DataLib.getSuperforms(multiVaultData.superformIds); IERC20 underlying; uint256 numberOfVaults = multiVaultData.superformIds.length; bool fulfilment; bool errors; for (uint256 i; i < numberOfVaults; ++i) { /// @dev it is not possible in theory to have multiVaultData.amounts to be 0 at this point /// @dev this is due to the fact that 0 values are moved in updateDeposit which must always run prior to /// processing the payload /// @dev this check is added here only for sanity purposes and full coverage of the line is not possible if (multiVaultData.amounts[i] != 0) { underlying = IERC20(_getVaultAsset(superforms[i])); if (underlying.balanceOf(address(this)) >= multiVaultData.amounts[i]) { underlying.safeIncreaseAllowance(superforms[i], multiVaultData.amounts[i]); LiqRequest memory emptyRequest; /// @notice If a given deposit fails, we are minting 0 SPs back on source (slight gas waste) try IBaseForm(superforms[i]).xChainDepositIntoVault( InitSingleVaultData({ payloadId: multiVaultData.payloadId, superformId: multiVaultData.superformIds[i], amount: multiVaultData.amounts[i], outputAmount: multiVaultData.outputAmounts[i], maxSlippage: multiVaultData.maxSlippages[i], liqData: emptyRequest, hasDstSwap: false, retain4626: multiVaultData.retain4626s[i], receiverAddress: multiVaultData.receiverAddress, extraFormData: multiVaultData.extraFormData }), srcSender_, srcChainId_ ) returns (uint256 shares) { if (shares != 0 && !multiVaultData.retain4626s[i]) { fulfilment = true; /// @dev marks the indexes that require a callback mint of shares (successful) multiVaultData.amounts[i] = shares; } else { multiVaultData.amounts[i] = 0; } } catch { /// @dev cleaning unused approval underlying.safeDecreaseAllowance(superforms[i], multiVaultData.amounts[i]); /// @dev if any deposit fails, we mark errors as true and add it to failedDepositSuperformIds /// mapping for future rescuing errors = true; failedDeposits[payloadId_].superformIds.push(multiVaultData.superformIds[i]); /// @dev clearing multiVaultData.amounts so that in case that fulfillment is true these amounts /// are not minted multiVaultData.amounts[i] = 0; failedDeposits[payloadId_].settlementToken.push(_getVaultAsset(superforms[i])); failedDeposits[payloadId_].settleFromDstSwapper.push(false); } } else { revert Error.BRIDGE_TOKENS_PENDING(); } } } if (errors) { emit FailedXChainDeposits(payloadId_); } /// @dev issue superPositions if at least one vault deposit passed if (fulfilment) { return _multiReturnData( srcSender_, multiVaultData.payloadId, TransactionType.DEPOSIT, CallbackType.RETURN, multiVaultData.superformIds, multiVaultData.amounts ); } return ""; } function _singleWithdrawal( uint256 payloadId_, bytes memory payload_, address srcSender_, uint64 srcChainId_ ) internal returns (bytes memory) { InitSingleVaultData memory singleVaultData = abi.decode(payload_, (InitSingleVaultData)); singleVaultData.extraFormData = abi.encode(payloadId_, 0); if (!_isSuperform(singleVaultData.superformId)) { revert Error.SUPERFORM_ID_NONEXISTENT(); } /// @dev Withdraw from superform try IBaseForm(_getSuperform(singleVaultData.superformId)).xChainWithdrawFromVault( singleVaultData, srcSender_, srcChainId_ ) { // Handle the case when the external call succeeds } catch { // Handle the case when the external call reverts for whatever reason /// https://solidity-by-example.org/try-catch/ return _singleReturnData( srcSender_, singleVaultData.payloadId, TransactionType.WITHDRAW, CallbackType.FAIL, singleVaultData.superformId, singleVaultData.amount ); } return ""; } function _singleDeposit( uint256 payloadId_, bytes memory payload_, address srcSender_, uint64 srcChainId_ ) internal returns (bytes memory) { InitSingleVaultData memory singleVaultData = abi.decode(payload_, (InitSingleVaultData)); address superform_ = _getSuperform(singleVaultData.superformId); address vaultAsset = _getVaultAsset(superform_); IERC20 underlying = IERC20(vaultAsset); if (underlying.balanceOf(address(this)) >= singleVaultData.amount) { underlying.safeIncreaseAllowance(superform_, singleVaultData.amount); /// @dev deposit to superform try IBaseForm(superform_).xChainDepositIntoVault(singleVaultData, srcSender_, srcChainId_) returns ( uint256 shares ) { if (shares != 0 && !singleVaultData.retain4626) { return _singleReturnData( srcSender_, singleVaultData.payloadId, TransactionType.DEPOSIT, CallbackType.RETURN, singleVaultData.superformId, shares ); } } catch { /// @dev cleaning unused approval underlying.safeDecreaseAllowance(superform_, singleVaultData.amount); /// @dev if any deposit fails, add it to failedDepositSuperformIds mapping for future rescuing failedDeposits[payloadId_].superformIds.push(singleVaultData.superformId); failedDeposits[payloadId_].settlementToken.push(vaultAsset); failedDeposits[payloadId_].settleFromDstSwapper.push(false); emit FailedXChainDeposits(payloadId_); } } else { revert Error.BRIDGE_TOKENS_PENDING(); } return ""; } function _processAck(uint256 payloadId_, uint64 srcChainId_, bytes memory returnMessage_) internal { /// @dev if deposits succeeded or some withdrawal failed, dispatch a callback if (returnMessage_.length != 0) { uint8[] memory ambIds = msgAMBs[payloadId_]; (, bytes memory extraData) = IPaymentHelper(_getAddress(keccak256("PAYMENT_HELPER"))).calculateAMBData( srcChainId_, ambIds, returnMessage_ ); _dispatchPayload(msg.sender, ambIds, srcChainId_, returnMessage_, extraData); } } /// @notice depositSync and withdrawSync internal method for sending message back to the source chain function _multiReturnData( address srcSender_, uint256 payloadId_, TransactionType txType, CallbackType returnType_, uint256[] memory superformIds_, uint256[] memory amounts_ ) internal view returns (bytes memory) { /// @dev Send Data to Source to issue superform positions (failed withdraws and successful deposits) return abi.encode( AMBMessage( DataLib.packTxInfo( uint8(txType), uint8(returnType_), 1, _getStateRegistryId(address(this)), srcSender_, CHAIN_ID ), abi.encode(ReturnMultiData(payloadId_, superformIds_, amounts_)) ) ); } /// @notice depositSync and withdrawSync internal method for sending message back to the source chain function _singleReturnData( address srcSender_, uint256 payloadId_, TransactionType txType, CallbackType returnType_, uint256 superformId_, uint256 amount_ ) internal view returns (bytes memory) { /// @dev Send Data to Source to issue superform positions (failed withdraws and successful deposits) return abi.encode( AMBMessage( DataLib.packTxInfo( uint8(txType), uint8(returnType_), 0, _getStateRegistryId(address(this)), srcSender_, CHAIN_ID ), abi.encode(ReturnSingleData(payloadId_, superformId_, amount_)) ) ); } /// @dev calls the function to update the proof during payload update function _updatePayload( uint256 payloadId_, bytes32 prevPayloadProof, bytes memory newPayloadBody, uint256 prevPayloadHeader, PayloadState finalState ) internal { bytes32 newPayloadProof = AMBMessage(prevPayloadHeader, newPayloadBody).computeProof(); if (newPayloadProof != prevPayloadProof) { messageQuorum[newPayloadProof] = messageQuorum[prevPayloadProof]; delete messageQuorum[prevPayloadProof]; } payloadBody[payloadId_] = newPayloadBody; payloadTracking[payloadId_] = finalState; emit PayloadUpdated(payloadId_); } /// @dev fetch vault asset and valid it against the final token function _fetchAndValidateFinalToken( uint256 superformId_, address finalToken_, bool validateInsideTry_ ) internal view returns (address vaultAsset_) { try IBaseForm(_getSuperform(superformId_)).getVaultAsset() returns (address asset_) { if (validateInsideTry_ && asset_ != finalToken_) { revert Error.INVALID_UPDATE_FINAL_TOKEN(); } vaultAsset_ = asset_; } catch { /// @dev if its error, we just consider asset as zero address } /// @dev vaultAsset_ will be address(0) if it does not enter the loop if (!validateInsideTry_ && vaultAsset_ != finalToken_) { revert Error.INVALID_UPDATE_FINAL_TOKEN(); } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; import { IBaseStateRegistry } from "src/interfaces/IBaseStateRegistry.sol"; import { IAmbImplementation } from "src/interfaces/IAmbImplementation.sol"; import { IQuorumManager } from "src/interfaces/IQuorumManager.sol"; import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; import { Error } from "src/libraries/Error.sol"; import { ProofLib } from "src/libraries/ProofLib.sol"; import { PayloadState, AMBMessage, AMBExtraData } from "src/types/DataTypes.sol"; /// @title BaseStateRegistry /// @dev Contract module that allows inheriting contracts to implement crosschain messaging & processing mechanisms. /// @dev this is a lightweight version that allows only dispatching and receiving crosschain /// @dev payloads (messages). Inheriting children contracts have the flexibility to define their own processing /// mechanisms. /// @author Zeropoint Labs abstract contract BaseStateRegistry is IBaseStateRegistry { using ProofLib for AMBMessage; using ProofLib for bytes; ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// ISuperRegistry public immutable superRegistry; uint64 public immutable CHAIN_ID; ////////////////////////////////////////////////////////////// // STATE VARIABLES // ////////////////////////////////////////////////////////////// uint256 public payloadsCount; /// @dev stores received payload after assigning them an unique identifier upon receiving mapping(uint256 => bytes) public payloadBody; /// @dev stores received payload's header (txInfo) mapping(uint256 => uint256) public payloadHeader; /// @dev stores a proof's quorum mapping(bytes32 => uint256) public messageQuorum; /// @dev maps payloads to their current status mapping(uint256 => PayloadState) public payloadTracking; /// @dev maps payloads to the amb ids that delivered them mapping(uint256 => uint8[]) internal msgAMBs; ////////////////////////////////////////////////////////////// // MODIFIERS // ////////////////////////////////////////////////////////////// /// @dev inheriting contracts should override this function based on functionality modifier onlySender() virtual { _; } /// @dev ensures that only added AMB implementations are accepted modifier onlyValidAmbImplementation() { if (!superRegistry.isValidAmbImpl(msg.sender)) { revert Error.NOT_AMB_IMPLEMENTATION(); } _; } ////////////////////////////////////////////////////////////// // CONSTRUCTOR // ////////////////////////////////////////////////////////////// constructor(ISuperRegistry superRegistry_) { if (block.chainid > type(uint64).max) { revert Error.BLOCK_CHAIN_ID_OUT_OF_BOUNDS(); } CHAIN_ID = uint64(block.chainid); superRegistry = superRegistry_; } ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// /// @inheritdoc IBaseStateRegistry function getMessageAMB(uint256 payloadId_) external view override returns (uint8[] memory) { return msgAMBs[payloadId_]; } ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// /// @inheritdoc IBaseStateRegistry function dispatchPayload( address srcSender_, uint8[] memory ambIds_, uint64 dstChainId_, bytes memory message_, bytes memory extraData_ ) external payable override onlySender { _dispatchPayload(srcSender_, ambIds_, dstChainId_, message_, extraData_); } /// @inheritdoc IBaseStateRegistry function receivePayload(uint64 srcChainId_, bytes memory message_) external override onlyValidAmbImplementation { AMBMessage memory data = abi.decode(message_, (AMBMessage)); /// @dev proofHash will always be 32 bytes length due to keccak256 if (data.params.length == 32) { bytes32 proofHash = abi.decode(data.params, (bytes32)); ++messageQuorum[proofHash]; emit ProofReceived(proofHash); } else { /// @dev if message, store header and body of it ++payloadsCount; payloadHeader[payloadsCount] = data.txInfo; (msgAMBs[payloadsCount], payloadBody[payloadsCount]) = abi.decode(data.params, (uint8[], bytes)); emit PayloadReceived(srcChainId_, CHAIN_ID, payloadsCount); } } /// @inheritdoc IBaseStateRegistry function processPayload(uint256 payloadId_) external payable virtual override; ////////////////////////////////////////////////////////////// // INTERNAL FUNCTIONS // ////////////////////////////////////////////////////////////// function _dispatchPayload( address srcSender_, uint8[] memory ambIds_, uint64 dstChainId_, bytes memory message_, bytes memory extraData_ ) internal { AMBMessage memory data = abi.decode(message_, (AMBMessage)); uint256 len = ambIds_.length; if (len == 0) { revert Error.ZERO_AMB_ID_LENGTH(); } /// @dev revert here if quorum requirements might fail on the remote chain if (len - 1 < _getQuorum(dstChainId_)) { revert Error.INSUFFICIENT_QUORUM(); } AMBExtraData memory d = abi.decode(extraData_, (AMBExtraData)); _getAMBImpl(ambIds_[0]).dispatchPayload{ value: d.gasPerAMB[0] }( srcSender_, dstChainId_, abi.encode(AMBMessage(data.txInfo, abi.encode(ambIds_, data.params))), d.extraDataPerAMB[0] ); if (len > 1) { data.params = message_.computeProofBytes(); /// @dev i starts from 1 since 0 is primary amb id which dispatches the message itself for (uint8 i = 1; i < len; ++i) { if (ambIds_[i] == ambIds_[0]) { revert Error.INVALID_PROOF_BRIDGE_ID(); } if (i - 1 != 0 && ambIds_[i] <= ambIds_[i - 1]) { revert Error.INVALID_PROOF_BRIDGE_IDS(); } /// @dev proof is dispatched in the form of a payload _getAMBImpl(ambIds_[i]).dispatchPayload{ value: d.gasPerAMB[i] }( srcSender_, dstChainId_, abi.encode(data), d.extraDataPerAMB[i] ); } } } /// @dev returns the required quorum for the src chain id from super registry /// @param chainId_ is the src chain id /// @return the quorum configured for the chain id function _getQuorum(uint64 chainId_) internal view returns (uint256) { return IQuorumManager(address(superRegistry)).getRequiredMessagingQuorum(chainId_); } /// @dev returns the amb id for address function _getAmbAddress(uint8 id_) internal view returns (address amb) { return superRegistry.getAmbAddress(id_); } function _getAMBImpl(uint8 id_) internal view returns (IAmbImplementation ambImplementation) { ambImplementation = IAmbImplementation(_getAmbAddress(id_)); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; /// @title ICoreStateRegistry /// @dev Interface for CoreStateRegistry /// @author ZeroPoint Labs interface ICoreStateRegistry { ////////////////////////////////////////////////////////////// // STRUCTS // ////////////////////////////////////////////////////////////// /// @dev holds all information about a failed deposit mapped to a payload id /// @param superformIds is an array of failing superform ids /// @param settlementToken is an array of tokens to be refunded for the failing superform /// @param amounts is an array of amounts of settlementToken to be refunded /// @param receiverAddress is the users refund address /// @param lastProposedTime indicates the rescue proposal timestamp struct FailedDeposit { uint256[] superformIds; address[] settlementToken; uint256[] amounts; bool[] settleFromDstSwapper; address receiverAddress; uint256 lastProposedTimestamp; } ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// /// @dev is emitted when any deposit fails event FailedXChainDeposits(uint256 indexed payloadId); /// @dev is emitted when a rescue is proposed for failed deposits in a payload event RescueProposed( uint256 indexed payloadId, uint256[] superformIds, uint256[] proposedAmount, uint256 proposedTime ); /// @dev is emitted when an user disputed his refund amounts event RescueDisputed(uint256 indexed payloadId); /// @dev is emitted when deposit rescue is finalized event RescueFinalized(uint256 indexed payloadId); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// /// @dev allows users to read the superformIds that failed in a specific payloadId_ /// @param payloadId_ is the identifier of the cross-chain payload. /// @return superformIds is the identifiers of superforms in the payloadId that got failed. /// @return amounts is the amounts of refund tokens issues /// @return lastProposedTime is the refund proposed time function getFailedDeposits(uint256 payloadId_) external view returns (uint256[] memory superformIds, uint256[] memory amounts, uint256 lastProposedTime); /// @dev used internally for try/catching /// @param finalAmount_ is the final amount of tokens received /// @param amount_ is the indicated amount of tokens to be received /// @param maxSlippage_ is the amount of acceptable slippage for the transaction function validateSlippage(uint256 finalAmount_, uint256 amount_, uint256 maxSlippage_) external view returns (bool); ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// /// @dev allows accounts with {CORE_STATE_REGISTRY_UPDATER_ROLE} to modify a received cross-chain deposit payload. /// @param payloadId_ is the identifier of the cross-chain payload to be updated. /// @param finalTokens_ is the token received by the core state registry. /// @param finalAmounts_ is the amount to be updated. /// NOTE: amounts cannot be updated beyond user specified safe slippage limit. function updateDepositPayload( uint256 payloadId_, address[] calldata finalTokens_, uint256[] calldata finalAmounts_ ) external; /// @dev allows accounts with {CORE_STATE_REGISTRY_UPDATER_ROLE} to modify a received cross-chain withdraw payload. /// @param payloadId_ is the identifier of the cross-chain payload to be updated. /// @param txData_ is the transaction data to be updated. function updateWithdrawPayload(uint256 payloadId_, bytes[] calldata txData_) external; /// @dev allows accounts with {CORE_STATE_REGISTRY_PROCESSOR_ROLE} to rescue tokens on failed deposits /// @param payloadId_ is the identifier of the cross-chain payload. /// @param proposedAmounts_ is the array of proposed rescue amounts. function proposeRescueFailedDeposits(uint256 payloadId_, uint256[] memory proposedAmounts_) external; /// @dev allows refund receivers to challenge their final receiving token amounts on failed deposits /// @param payloadId_ is the identifier of the cross-chain payload /// @notice should challenge within the delay window configured on SuperRegistry function disputeRescueFailedDeposits(uint256 payloadId_) external; /// @dev allows anyone to settle refunds for unprocessed/failed deposits past the challenge period /// @param payloadId_ is the identifier of the cross-chain payload function finalizeRescueFailedDeposits(uint256 payloadId_) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; import { InitSingleVaultData } from "src/types/DataTypes.sol"; import { IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol"; import { IERC4626 } from "openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; /// @title IBaseForm /// @dev Interface for BaseForm /// @author ZeroPoint Labs interface IBaseForm is IERC165 { ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// /// @dev is emitted when a new vault is added by the admin. event VaultAdded(uint256 indexed id, IERC4626 indexed vault); /// @dev is emitted when a payload is processed by the destination contract. event Processed( uint64 indexed srcChainID, uint64 indexed dstChainId, uint256 indexed srcPayloadId, uint256 amount, address vault ); /// @dev is emitted when an emergency withdrawal is processed event EmergencyWithdrawalProcessed(address indexed refundAddress, uint256 indexed amount); /// @dev is emitted when dust is forwarded to the paymaster event FormDustForwardedToPaymaster(address indexed token, uint256 indexed amount); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// /// @notice get Superform name of the ERC20 vault representation /// @return The ERC20 name function superformYieldTokenName() external view returns (string memory); /// @notice get Superform symbol of the ERC20 vault representation /// @return The ERC20 symbol function superformYieldTokenSymbol() external view returns (string memory); /// @notice get the state registry id associated with the vault function getStateRegistryId() external view returns (uint8); /// @notice Returns the vault address /// @return The address of the vault function getVaultAddress() external view returns (address); /// @notice Returns the vault address /// @return The address of the vault asset function getVaultAsset() external view returns (address); /// @notice Returns the name of the vault. /// @return The name of the vault function getVaultName() external view returns (string memory); /// @notice Returns the symbol of a vault. /// @return The symbol associated with a vault function getVaultSymbol() external view returns (string memory); /// @notice Returns the number of decimals in a vault for accounting purposes /// @return The number of decimals in the vault balance function getVaultDecimals() external view returns (uint256); /// @notice Returns the amount of underlying tokens each share of a vault is worth. /// @return The pricePerVaultShare value function getPricePerVaultShare() external view returns (uint256); /// @notice Returns the amount of vault shares owned by the form. /// @return The form's vault share balance function getVaultShareBalance() external view returns (uint256); /// @notice get the total amount of underlying managed in the ERC4626 vault function getTotalAssets() external view returns (uint256); /// @notice get the total amount of unredeemed vault shares in circulation function getTotalSupply() external view returns (uint256); /// @notice get the total amount of assets received if shares are actually redeemed /// @notice https://eips.ethereum.org/EIPS/eip-4626 function getPreviewPricePerVaultShare() external view returns (uint256); /// @dev API may need to know state of funds deployed function previewDepositTo(uint256 assets_) external view returns (uint256); /// @notice positionBalance() -> .vaultIds&destAmounts /// @return how much of an asset + interest (accrued) is to withdraw from the Vault function previewWithdrawFrom(uint256 assets_) external view returns (uint256); /// @dev API may need to know state of funds deployed function previewRedeemFrom(uint256 shares_) external view returns (uint256); ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// /// @dev process same chain id deposits /// @param singleVaultData_ A bytes representation containing all the data required to make a form action /// @param srcSender_ The address of the sender of the transaction /// @return shares The amount of vault shares received function directDepositIntoVault( InitSingleVaultData memory singleVaultData_, address srcSender_ ) external payable returns (uint256 shares); /// @dev process same chain id deposits /// @param singleVaultData_ A bytes representation containing all the data required to make a form action /// @param srcSender_ The address of the sender of the transaction /// @param srcChainId_ The chain id of the source chain /// @return shares The amount of vault shares received /// @dev is shares is `0` then no further action/acknowledgement needs to be sent function xChainDepositIntoVault( InitSingleVaultData memory singleVaultData_, address srcSender_, uint64 srcChainId_ ) external returns (uint256 shares); /// @dev process withdrawal of asset from a vault /// @param singleVaultData_ A bytes representation containing all the data required to make a form action /// @param srcSender_ The address of the sender of the transaction /// @return assets The amount of assets received function directWithdrawFromVault( InitSingleVaultData memory singleVaultData_, address srcSender_ ) external returns (uint256 assets); /// @dev process withdrawal of asset from a vault /// @param singleVaultData_ A bytes representation containing all the data required to make a form action /// @param srcSender_ The address of the sender of the transaction /// @param srcChainId_ The chain id of the source chain /// @return assets The amount of assets received function xChainWithdrawFromVault( InitSingleVaultData memory singleVaultData_, address srcSender_, uint64 srcChainId_ ) external returns (uint256 assets); /// @dev process withdrawal of shares if form is paused /// @param receiverAddress_ The address to refund the shares to /// @param amount_ The amount of vault shares to refund function emergencyWithdraw(address receiverAddress_, uint256 amount_) external; /// @dev moves all dust in the contract to Paymaster contract /// @param token_ The address of the token to forward function forwardDustToPaymaster(address token_) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; /// @title Bridge Validator Interface /// @dev Interface all Bridge Validators must follow /// @author Zeropoint Labs interface IBridgeValidator { ////////////////////////////////////////////////////////////// // STRUCTS // ////////////////////////////////////////////////////////////// struct ValidateTxDataArgs { bytes txData; uint64 srcChainId; uint64 dstChainId; uint64 liqDstChainId; bool deposit; address superform; address receiverAddress; address liqDataToken; address liqDataInterimToken; } ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// /// @dev validates the receiver of the liquidity request /// @param txData_ is the txData of the cross chain deposit /// @param receiver_ is the address of the receiver to validate /// @return valid_ if the address is valid function validateReceiver(bytes calldata txData_, address receiver_) external view returns (bool valid_); /// @dev validates the txData of a cross chain deposit /// @param args_ the txData arguments to validate in txData /// @return hasDstSwap if the txData contains a destination swap function validateTxData(ValidateTxDataArgs calldata args_) external view returns (bool hasDstSwap); /// @dev decodes the txData and returns the amount of input token on source /// @param txData_ is the txData of the cross chain deposit /// @param genericSwapDisallowed_ true if generic swaps are disallowed /// @return amount_ the amount expected function decodeAmountIn( bytes calldata txData_, bool genericSwapDisallowed_ ) external view returns (uint256 amount_); /// @dev decodes neccesary information for processing swaps on the destination chain /// @param txData_ is the txData to be decoded /// @return token_ is the address of the token /// @return amount_ the amount expected function decodeDstSwap(bytes calldata txData_) external pure returns (address token_, uint256 amount_); /// @dev decodes the final output token address (for only direct chain actions!) /// @param txData_ is the txData to be decoded /// @return token_ the address of the token function decodeSwapOutputToken(bytes calldata txData_) external pure returns (address token_); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; /// @title IDstSwapper /// @dev Interface for DstSwapper /// @author Zeropoint Labs interface IDstSwapper { ////////////////////////////////////////////////////////////// // STRUCTS // ////////////////////////////////////////////////////////////// struct FailedSwap { address interimToken; uint256 amount; } ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// /// @dev is emitted when the super registry is updated. event SuperRegistryUpdated(address indexed superRegistry); /// @dev is emitted when a dst swap transaction is processed event SwapProcessed( uint256 indexed payloadId, uint256 indexed index, uint256 indexed bridgeId, uint256 finalAmount ); /// @dev is emitted when a dst swap fails and intermediary tokens are sent to CoreStateRegistry for rescue event SwapFailed( uint256 indexed payloadId, uint256 indexed index, address indexed intermediaryToken, uint256 amount ); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// /// @notice returns the swapped amounts (if dst swap is successful) /// @param payloadId_ is the id of payload /// @param index_ represents the index in the payload (0 for single vault payload) /// @return amount is the amount forwarded to core state registry after the swap function swappedAmount(uint256 payloadId_, uint256 index_) external view returns (uint256 amount); /// @notice returns the interim amounts (if dst swap is failing) /// @param payloadId_ is the id of payload /// @param index_ represents the index in the payload (0 for single vault payload) /// @return interimToken is the token that is to be refunded /// @return amount is the amount of interim token to be refunded function getPostDstSwapFailureUpdatedTokenAmount( uint256 payloadId_, uint256 index_ ) external view returns (address interimToken, uint256 amount); ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// /// @notice will process dst swap through a liquidity bridge /// @param payloadId_ represents the id of the payload /// @param bridgeId_ represents the id of liquidity bridge used /// @param txData_ represents the transaction data generated by liquidity bridge API. function processTx(uint256 payloadId_, uint8 bridgeId_, bytes calldata txData_) external; /// @notice will process dst swaps in batch through a liquidity bridge /// @param payloadId_ represents the array of payload ids used /// @param indices_ represents the index of the superformid in the payload /// @param bridgeIds_ represents the array of ids of liquidity bridges used /// @param txDatas_ represents the array of transaction data generated by liquidity bridge API function batchProcessTx( uint256 payloadId_, uint256[] calldata indices_, uint8[] calldata bridgeIds_, bytes[] calldata txDatas_ ) external; /// @notice updates the amounts of intermediary tokens stuck because of failing dst swap /// @param payloadId_ represents the id of the payload /// @param interimToken_ is the intermediary token that cannot be swapped to the vault underlying /// @param amount_ is the amount of the intermediary token function updateFailedTx(uint256 payloadId_, address interimToken_, uint256 amount_) external; /// @notice updates the amounts of intermediary tokens stuck because of failing dst swap in batch /// @param payloadId_ represents the id of the payload /// @param indices_ represents the failing indices in the payload /// @param interimTokens_ is the list of intermediary tokens that cannot be swapped /// @param amounts_ are the amount of intermediary tokens that need to be refunded to the user function batchUpdateFailedTx( uint256 payloadId_, uint256[] calldata indices_, address[] calldata interimTokens_, uint256[] calldata amounts_ ) external; /// @notice is a privileged function that allows Core State Registry to process refunds /// @param user_ is the final refund receiver of the interimToken_ /// @param interimToken_ is the refund token /// @param amount_ is the refund amount function processFailedTx(address user_, address interimToken_, uint256 amount_) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; import { IAccessControl } from "openzeppelin-contracts/contracts/access/IAccessControl.sol"; /// @title ISuperRBAC /// @dev Interface for SuperRBAC /// @author Zeropoint Labs interface ISuperRBAC is IAccessControl { ////////////////////////////////////////////////////////////// // STRUCTS // ////////////////////////////////////////////////////////////// struct InitialRoleSetup { address admin; address emergencyAdmin; address paymentAdmin; address csrProcessor; address tlProcessor; address brProcessor; address csrUpdater; address srcVaaRelayer; address dstSwapper; address csrRescuer; address csrDisputer; } ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// /// @dev is emitted when superRegistry is set event SuperRegistrySet(address indexed superRegistry); /// @dev is emitted when an admin is set for a role event RoleAdminSet(bytes32 role, bytes32 adminRole); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// /// @dev returns the id of the protocol admin role function PROTOCOL_ADMIN_ROLE() external view returns (bytes32); /// @dev returns the id of the emergency admin role function EMERGENCY_ADMIN_ROLE() external view returns (bytes32); /// @dev returns the id of the payment admin role function PAYMENT_ADMIN_ROLE() external view returns (bytes32); /// @dev returns the id of the broadcaster role function BROADCASTER_ROLE() external view returns (bytes32); /// @dev returns the id of the core state registry processor role function CORE_STATE_REGISTRY_PROCESSOR_ROLE() external view returns (bytes32); /// @dev returns the id of the timelock state registry processor role function TIMELOCK_STATE_REGISTRY_PROCESSOR_ROLE() external view returns (bytes32); /// @dev returns the id of the broadcast state registry processor role function BROADCAST_STATE_REGISTRY_PROCESSOR_ROLE() external view returns (bytes32); /// @dev returns the id of the core state registry updater role function CORE_STATE_REGISTRY_UPDATER_ROLE() external view returns (bytes32); /// @dev returns the id of the dst swapper role function DST_SWAPPER_ROLE() external view returns (bytes32); /// @dev returns the id of the core state registry rescuer role function CORE_STATE_REGISTRY_RESCUER_ROLE() external view returns (bytes32); /// @dev returns the id of the core state registry rescue disputer role function CORE_STATE_REGISTRY_DISPUTER_ROLE() external view returns (bytes32); /// @dev returns the id of wormhole vaa relayer role function WORMHOLE_VAA_RELAYER_ROLE() external view returns (bytes32); /// @dev returns whether the given address has the protocol admin role /// @param admin_ the address to check function hasProtocolAdminRole(address admin_) external view returns (bool); /// @dev returns whether the given address has the emergency admin role /// @param admin_ the address to check function hasEmergencyAdminRole(address admin_) external view returns (bool); ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// /// @dev updates the super registry address function setSuperRegistry(address superRegistry_) external; /// @dev configures a new role in superForm /// @param role_ the role to set /// @param adminRole_ the admin role to set as admin function setRoleAdmin(bytes32 role_, bytes32 adminRole_) external; /// @dev revokes the role_ from superRegistryAddressId_ on all chains /// @param role_ the role to revoke /// @param extraData_ amb config if broadcasting is required /// @param superRegistryAddressId_ the super registry address id function revokeRoleSuperBroadcast( bytes32 role_, bytes memory extraData_, bytes32 superRegistryAddressId_ ) external payable; /// @dev allows sync of global roles from different chains using broadcast registry /// @notice may not work for all roles function stateSyncBroadcast(bytes memory data_) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; /// @title ISuperformFactory /// @dev Interface for SuperformFactory /// @author ZeroPoint Labs interface ISuperformFactory { ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// enum PauseStatus { NON_PAUSED, PAUSED } ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// /// @dev emitted when a new formImplementation is entered into the factory /// @param formImplementation is the address of the new form implementation /// @param formImplementationId is the id of the formImplementation /// @param formStateRegistryId is any additional state registry id of the formImplementation event FormImplementationAdded( address indexed formImplementation, uint256 indexed formImplementationId, uint8 indexed formStateRegistryId ); /// @dev emitted when a new Superform is created /// @param formImplementationId is the id of the form implementation /// @param vault is the address of the vault /// @param superformId is the id of the superform /// @param superform is the address of the superform event SuperformCreated( uint256 indexed formImplementationId, address indexed vault, uint256 indexed superformId, address superform ); /// @dev emitted when a new SuperRegistry is set /// @param superRegistry is the address of the super registry event SuperRegistrySet(address indexed superRegistry); /// @dev emitted when a form implementation is paused /// @param formImplementationId is the id of the form implementation /// @param paused is the new paused status event FormImplementationPaused(uint256 indexed formImplementationId, PauseStatus indexed paused); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// /// @dev returns the number of forms /// @return forms_ is the number of forms function getFormCount() external view returns (uint256 forms_); /// @dev returns the number of superforms /// @return superforms_ is the number of superforms function getSuperformCount() external view returns (uint256 superforms_); /// @dev returns the address of a form implementation /// @param formImplementationId_ is the id of the form implementation /// @return formImplementation_ is the address of the form implementation function getFormImplementation(uint32 formImplementationId_) external view returns (address formImplementation_); /// @dev returns the form state registry id of a form implementation /// @param formImplementationId_ is the id of the form implementation /// @return stateRegistryId_ is the additional state registry id of the form function getFormStateRegistryId(uint32 formImplementationId_) external view returns (uint8 stateRegistryId_); /// @dev returns the paused status of form implementation /// @param formImplementationId_ is the id of the form implementation /// @return paused_ is the current paused status of the form formImplementationId_ function isFormImplementationPaused(uint32 formImplementationId_) external view returns (bool paused_); /// @dev returns the address of a superform /// @param superformId_ is the id of the superform /// @return superform_ is the address of the superform /// @return formImplementationId_ is the id of the form implementation /// @return chainId_ is the chain id function getSuperform(uint256 superformId_) external pure returns (address superform_, uint32 formImplementationId_, uint64 chainId_); /// @dev returns if an address has been added to a Form /// @param superformId_ is the id of the superform /// @return isSuperform_ bool if it exists function isSuperform(uint256 superformId_) external view returns (bool isSuperform_); /// @dev Reverse query of getSuperform, returns all superforms for a given vault /// @param vault_ is the address of a vault /// @return superformIds_ is the id of the superform /// @return superforms_ is the address of the superform function getAllSuperformsFromVault(address vault_) external view returns (uint256[] memory superformIds_, address[] memory superforms_); ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// /// @dev allows an admin to add a Form implementation to the factory /// @param formImplementation_ is the address of a form implementation /// @param formImplementationId_ is the id of the form implementation (generated off-chain and equal in all chains) /// @param formStateRegistryId_ is the id of any additional state registry for that form /// @dev formStateRegistryId_ 1 is default for all form implementations, pass in formStateRegistryId_ only if an /// additional state registry is required function addFormImplementation( address formImplementation_, uint32 formImplementationId_, uint8 formStateRegistryId_ ) external; /// @dev To add new vaults to Form implementations, fusing them together into Superforms /// @param formImplementationId_ is the form implementation we want to attach the vault to /// @param vault_ is the address of the vault /// @return superformId_ is the id of the created superform /// @return superform_ is the address of the created superform function createSuperform( uint32 formImplementationId_, address vault_ ) external returns (uint256 superformId_, address superform_); /// @dev to synchronize superforms added to different chains using broadcast registry /// @param data_ is the cross-chain superform id function stateSyncBroadcast(bytes memory data_) external payable; /// @dev allows an admin to change the status of a form /// @param formImplementationId_ is the id of the form implementation /// @param status_ is the new status /// @param extraData_ is optional & passed when broadcasting of status is needed function changeFormImplementationPauseStatus( uint32 formImplementationId_, PauseStatus status_, bytes memory extraData_ ) external payable; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; import { IERC1155A } from "ERC1155A/interfaces/IERC1155A.sol"; import { AMBMessage } from "../types/DataTypes.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; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; /// @title ISuperRegistry /// @dev Interface for SuperRegistry /// @author Zeropoint Labs interface ISuperRegistry { ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// /// @dev emitted when permit2 is set. event SetPermit2(address indexed permit2); /// @dev is emitted when an address is set. event AddressUpdated( bytes32 indexed protocolAddressId, uint64 indexed chainId, address indexed oldAddress, address newAddress ); /// @dev is emitted when a new token bridge is configured. event SetBridgeAddress(uint256 indexed bridgeId, address indexed bridgeAddress); /// @dev is emitted when a new bridge validator is configured. event SetBridgeValidator(uint256 indexed bridgeId, address indexed bridgeValidator); /// @dev is emitted when a new amb is configured. event SetAmbAddress(uint8 indexed ambId_, address indexed ambAddress_, bool indexed isBroadcastAMB_); /// @dev is emitted when a new state registry is configured. event SetStateRegistryAddress(uint8 indexed registryId_, address indexed registryAddress_); /// @dev is emitted when a new delay is configured. event SetDelay(uint256 indexed oldDelay_, uint256 indexed newDelay_); /// @dev is emitted when a new vault limit is configured event SetVaultLimitPerDestination(uint64 indexed chainId_, uint256 indexed vaultLimit_); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// /// @dev gets the deposit rescue delay function delay() external view returns (uint256); /// @dev returns the permit2 address function PERMIT2() external view returns (address); /// @dev returns the id of the superform router module function SUPERFORM_ROUTER() external view returns (bytes32); /// @dev returns the id of the superform factory module function SUPERFORM_FACTORY() external view returns (bytes32); /// @dev returns the id of the superform paymaster contract function PAYMASTER() external view returns (bytes32); /// @dev returns the id of the superform payload helper contract function PAYMENT_HELPER() external view returns (bytes32); /// @dev returns the id of the core state registry module function CORE_STATE_REGISTRY() external view returns (bytes32); /// @dev returns the id of the timelock form state registry module function TIMELOCK_STATE_REGISTRY() external view returns (bytes32); /// @dev returns the id of the broadcast state registry module function BROADCAST_REGISTRY() external view returns (bytes32); /// @dev returns the id of the super positions module function SUPER_POSITIONS() external view returns (bytes32); /// @dev returns the id of the super rbac module function SUPER_RBAC() external view returns (bytes32); /// @dev returns the id of the payload helper module function PAYLOAD_HELPER() external view returns (bytes32); /// @dev returns the id of the dst swapper keeper function DST_SWAPPER() external view returns (bytes32); /// @dev returns the id of the emergency queue function EMERGENCY_QUEUE() external view returns (bytes32); /// @dev returns the id of the superform receiver function SUPERFORM_RECEIVER() external view returns (bytes32); /// @dev returns the id of the payment admin keeper function PAYMENT_ADMIN() external view returns (bytes32); /// @dev returns the id of the core state registry processor keeper function CORE_REGISTRY_PROCESSOR() external view returns (bytes32); /// @dev returns the id of the broadcast registry processor keeper function BROADCAST_REGISTRY_PROCESSOR() external view returns (bytes32); /// @dev returns the id of the timelock form state registry processor keeper function TIMELOCK_REGISTRY_PROCESSOR() external view returns (bytes32); /// @dev returns the id of the core state registry updater keeper function CORE_REGISTRY_UPDATER() external view returns (bytes32); /// @dev returns the id of the core state registry updater keeper function CORE_REGISTRY_RESCUER() external view returns (bytes32); /// @dev returns the id of the core state registry updater keeper function CORE_REGISTRY_DISPUTER() external view returns (bytes32); /// @dev returns the id of the core state registry updater keeper function DST_SWAPPER_PROCESSOR() external view returns (bytes32); /// @dev gets the address of a contract on current chain /// @param id_ is the id of the contract function getAddress(bytes32 id_) external view returns (address); /// @dev gets the address of a contract on a target chain /// @param id_ is the id of the contract /// @param chainId_ is the chain id of that chain function getAddressByChainId(bytes32 id_, uint64 chainId_) external view returns (address); /// @dev gets the address of a bridge /// @param bridgeId_ is the id of a bridge /// @return bridgeAddress_ is the address of the form function getBridgeAddress(uint8 bridgeId_) external view returns (address bridgeAddress_); /// @dev gets the address of a bridge validator /// @param bridgeId_ is the id of a bridge /// @return bridgeValidator_ is the address of the form function getBridgeValidator(uint8 bridgeId_) external view returns (address bridgeValidator_); /// @dev gets the address of a amb /// @param ambId_ is the id of a bridge /// @return ambAddress_ is the address of the form function getAmbAddress(uint8 ambId_) external view returns (address ambAddress_); /// @dev gets the id of the amb /// @param ambAddress_ is the address of an amb /// @return ambId_ is the identifier of an amb function getAmbId(address ambAddress_) external view returns (uint8 ambId_); /// @dev gets the address of the registry /// @param registryId_ is the id of the state registry /// @return registryAddress_ is the address of the state registry function getStateRegistry(uint8 registryId_) external view returns (address registryAddress_); /// @dev gets the id of the registry /// @notice reverts if the id is not found /// @param registryAddress_ is the address of the state registry /// @return registryId_ is the id of the state registry function getStateRegistryId(address registryAddress_) external view returns (uint8 registryId_); /// @dev gets the safe vault limit /// @param chainId_ is the id of the remote chain /// @return vaultLimitPerDestination_ is the safe number of vaults to deposit /// without hitting out of gas error function getVaultLimitPerDestination(uint64 chainId_) external view returns (uint256 vaultLimitPerDestination_); /// @dev helps validate if an address is a valid state registry /// @param registryAddress_ is the address of the state registry /// @return valid_ a flag indicating if its valid. function isValidStateRegistry(address registryAddress_) external view returns (bool valid_); /// @dev helps validate if an address is a valid amb implementation /// @param ambAddress_ is the address of the amb implementation /// @return valid_ a flag indicating if its valid. function isValidAmbImpl(address ambAddress_) external view returns (bool valid_); /// @dev helps validate if an address is a valid broadcast amb implementation /// @param ambAddress_ is the address of the broadcast amb implementation /// @return valid_ a flag indicating if its valid. function isValidBroadcastAmbImpl(address ambAddress_) external view returns (bool valid_); ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// /// @dev sets the deposit rescue delay /// @param delay_ the delay in seconds before the deposit rescue can be finalized function setDelay(uint256 delay_) external; /// @dev sets the permit2 address /// @param permit2_ the address of the permit2 contract function setPermit2(address permit2_) external; /// @dev sets the safe vault limit /// @param chainId_ is the remote chain identifier /// @param vaultLimit_ is the max limit of vaults per transaction function setVaultLimitPerDestination(uint64 chainId_, uint256 vaultLimit_) external; /// @dev sets new addresses on specific chains. /// @param ids_ are the identifiers of the address on that chain /// @param newAddresses_ are the new addresses on that chain /// @param chainIds_ are the chain ids of that chain function batchSetAddress( bytes32[] calldata ids_, address[] calldata newAddresses_, uint64[] calldata chainIds_ ) external; /// @dev sets a new address on a specific chain. /// @param id_ the identifier of the address on that chain /// @param newAddress_ the new address on that chain /// @param chainId_ the chain id of that chain function setAddress(bytes32 id_, address newAddress_, uint64 chainId_) external; /// @dev allows admin to set the bridge address for an bridge id. /// @notice this function operates in an APPEND-ONLY fashion. /// @param bridgeId_ represents the bridge unique identifier. /// @param bridgeAddress_ represents the bridge address. /// @param bridgeValidator_ represents the bridge validator address. function setBridgeAddresses( uint8[] memory bridgeId_, address[] memory bridgeAddress_, address[] memory bridgeValidator_ ) external; /// @dev allows admin to set the amb address for an amb id. /// @notice this function operates in an APPEND-ONLY fashion. /// @param ambId_ represents the bridge unique identifier. /// @param ambAddress_ represents the bridge address. /// @param isBroadcastAMB_ represents whether the amb implementation supports broadcasting function setAmbAddress( uint8[] memory ambId_, address[] memory ambAddress_, bool[] memory isBroadcastAMB_ ) external; /// @dev allows admin to set the state registry address for an state registry id. /// @notice this function operates in an APPEND-ONLY fashion. /// @param registryId_ represents the state registry's unique identifier. /// @param registryAddress_ represents the state registry's address. function setStateRegistryAddress(uint8[] memory registryId_, address[] memory registryAddress_) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; import { MultiDstMultiVaultStateReq, MultiDstSingleVaultStateReq, SingleXChainMultiVaultStateReq, SingleXChainSingleVaultStateReq, SingleDirectSingleVaultStateReq, SingleDirectMultiVaultStateReq } from "src/types/DataTypes.sol"; /// @title IPaymentHelper /// @dev Interface for PaymentHelper /// @author ZeroPoint Labs interface IPaymentHelper { ////////////////////////////////////////////////////////////// // STRUCTS // ////////////////////////////////////////////////////////////// /// @param nativeFeedOracle is the native price feed oracle /// @param gasPriceOracle is the gas price oracle /// @param swapGasUsed is the swap gas params /// @param updateGasUsed is the update gas params /// @param depositGasUsed is the deposit per vault gas on the chain /// @param withdrawGasUsed is the withdraw per vault gas on the chain /// @param defaultNativePrice is the native price on the specified chain /// @param defaultGasPrice is the gas price on the specified chain /// @param dstGasPerByte is the gas per size of data on the specified chain /// @param ackGasCost is the gas cost for sending and processing from dst->src /// @param timelockCost is the extra cost for processing timelocked payloads /// @param emergencyCost is the extra cost for processing emergency payloads struct PaymentHelperConfig { address nativeFeedOracle; address gasPriceOracle; uint256 swapGasUsed; uint256 updateGasUsed; uint256 depositGasUsed; uint256 withdrawGasUsed; uint256 defaultNativePrice; uint256 defaultGasPrice; uint256 dstGasPerByte; uint256 ackGasCost; uint256 timelockCost; uint256 emergencyCost; } ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// event ChainConfigUpdated(uint64 indexed chainId_, uint256 indexed configType_, bytes config_); event ChainConfigAdded(uint64 chainId_, PaymentHelperConfig config_); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// /// @dev returns the amb overrides & gas to be used /// @param dstChainId_ is the unique dst chain identifier /// @param ambIds_ is the identifiers of arbitrary message bridges to be used /// @param message_ is the encoded cross-chain payload function calculateAMBData( uint64 dstChainId_, uint8[] calldata ambIds_, bytes memory message_ ) external view returns (uint256 totalFees, bytes memory extraData); /// @dev returns the amb overrides & gas to be used /// @return extraData the amb specific override information function getRegisterTransmuterAMBData() external view returns (bytes memory extraData); /// @dev estimates the gas fees for multiple destination and multi vault operation /// @param req_ is the request object containing all necessary data for the actual operation on SuperRouter /// @param isDeposit_ indicated if the datatype will be used for a deposit /// @return liqAmount is the amount of liquidity to be provided in native tokens /// @return srcAmount is the gas expense on source chain in native tokens /// @return dstAmount is the gas expense on dst chain in terms of src chain's native tokens /// @return totalAmount is the native_tokens to be sent along the transaction function estimateMultiDstMultiVault( MultiDstMultiVaultStateReq calldata req_, bool isDeposit_ ) external view returns (uint256 liqAmount, uint256 srcAmount, uint256 dstAmount, uint256 totalAmount); /// @dev estimates the gas fees for multiple destination and single vault operation /// @param req_ is the request object containing all necessary data for the actual operation on SuperRouter /// @param isDeposit_ indicated if the datatype will be used for a deposit /// @return liqAmount is the amount of liquidity to be provided in native tokens /// @return srcAmount is the gas expense on source chain in native tokens /// @return dstAmount is the gas expense on dst chain in terms of src chain's native tokens /// @return totalAmount is the native_tokens to be sent along the transaction function estimateMultiDstSingleVault( MultiDstSingleVaultStateReq calldata req_, bool isDeposit_ ) external view returns (uint256 liqAmount, uint256 srcAmount, uint256 dstAmount, uint256 totalAmount); /// @dev estimates the gas fees for single destination and multi vault operation /// @param req_ is the request object containing all necessary data for the actual operation on SuperRouter /// @param isDeposit_ indicated if the datatype will be used for a deposit /// @return liqAmount is the amount of liquidity to be provided in native tokens /// @return srcAmount is the gas expense on source chain in native tokens /// @return dstAmount is the gas expense on dst chain in terms of src chain's native tokens /// @return totalAmount is the native_tokens to be sent along the transaction function estimateSingleXChainMultiVault( SingleXChainMultiVaultStateReq calldata req_, bool isDeposit_ ) external view returns (uint256 liqAmount, uint256 srcAmount, uint256 dstAmount, uint256 totalAmount); /// @dev estimates the gas fees for single destination and single vault operation /// @param req_ is the request object containing all necessary data for the actual operation on SuperRouter /// @param isDeposit_ indicated if the datatype will be used for a deposit /// @return liqAmount is the amount of liquidity to be provided in native tokens /// @return srcAmount is the gas expense on source chain in native tokens /// @return dstAmount is the gas expense on dst chain in terms of src chain's native tokens /// @return totalAmount is the native_tokens to be sent along the transaction function estimateSingleXChainSingleVault( SingleXChainSingleVaultStateReq calldata req_, bool isDeposit_ ) external view returns (uint256 liqAmount, uint256 srcAmount, uint256 dstAmount, uint256 totalAmount); /// @dev estimates the gas fees for same chain operation /// @param req_ is the request object containing all necessary data for the actual operation on SuperRouter /// @param isDeposit_ indicated if the datatype will be used for a deposit /// @return liqAmount is the amount of liquidity to be provided in native tokens /// @return srcAmount is the gas expense on source chain in native tokens /// @return totalAmount is the native_tokens to be sent along the transaction function estimateSingleDirectSingleVault( SingleDirectSingleVaultStateReq calldata req_, bool isDeposit_ ) external view returns (uint256 liqAmount, uint256 srcAmount, uint256 totalAmount); /// @dev estimates the gas fees for multiple same chain operation /// @param req_ is the request object containing all necessary data for the actual operation on SuperRouter /// @param isDeposit_ indicated if the datatype will be used for a deposit /// @return liqAmount is the amount of liquidity to be provided in native tokens /// @return srcAmount is the gas expense on source chain in native tokens /// @return totalAmount is the native_tokens to be sent along the transaction function estimateSingleDirectMultiVault( SingleDirectMultiVaultStateReq calldata req_, bool isDeposit_ ) external view returns (uint256 liqAmount, uint256 srcAmount, uint256 totalAmount); /// @dev returns the gas fees estimation in native tokens if we send message through a combination of AMBs /// @param ambIds_ is the identifier of different AMBs /// @param dstChainId_ is the identifier of the destination chain /// @param message_ is the cross-chain message /// @param extraData_ is any amb-specific information /// @return ambFees is the native_tokens to be sent along the transaction for all the ambIds_ included function estimateAMBFees( uint8[] memory ambIds_, uint64 dstChainId_, bytes memory message_, bytes[] memory extraData_ ) external view returns (uint256 ambFees, uint256[] memory); /// @dev helps estimate the acknowledgement costs for amb processing /// @param payloadId_ is the payload identifier /// @return totalFees is the total fees to be paid in native tokens function estimateAckCost(uint256 payloadId_) external view returns (uint256 totalFees); /// @dev helps estimate the acknowledgement costs for amb processing without relying on payloadId (using max values) /// @param multi is the flag indicating if the payload is multi or single /// @param ackAmbIds is the list of ambIds to be used for acknowledgement /// @param srcChainId is the source chain identifier /// @return totalFees is the total fees to be paid in native tokens function estimateAckCostDefault( bool multi, uint8[] memory ackAmbIds, uint64 srcChainId ) external view returns (uint256 totalFees); /// @dev helps estimate the acknowledgement costs for amb processing without relying on payloadId (using max values) /// with source native amounts /// @param multi is the flag indicating if the payload is multi or single /// @param ackAmbIds is the list of ambIds to be used for acknowledgement /// @param srcChainId is the source chain identifier /// @return totalFees is the total fees to be paid in native tokens function estimateAckCostDefaultNativeSource( bool multi, uint8[] memory ackAmbIds, uint64 srcChainId ) external view returns (uint256 totalFees); ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// /// @dev admin can configure a remote chain for first time /// @param chainId_ is the identifier of new chain id /// @param config_ is the chain config function addRemoteChain(uint64 chainId_, PaymentHelperConfig calldata config_) external; /// @dev admin can specifically configure/update certain configuration of a remote chain /// @param chainId_ is the remote chain's identifier /// @param configType_ is the type of config from 1 -> 6 /// @param config_ is the encoded new configuration function updateRemoteChain(uint64 chainId_, uint256 configType_, bytes memory config_) external; /// @dev admin updates config for register transmuter amb params /// @param extraDataForTransmuter_ is the broadcast extra data function updateRegisterAERC20Params(bytes memory extraDataForTransmuter_) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; import { Error } from "src/libraries/Error.sol"; library DataLib { function packTxInfo( uint8 txType_, uint8 callbackType_, uint8 multi_, uint8 registryId_, address srcSender_, uint64 srcChainId_ ) internal pure returns (uint256 txInfo) { txInfo = uint256(txType_); txInfo |= uint256(callbackType_) << 8; txInfo |= uint256(multi_) << 16; txInfo |= uint256(registryId_) << 24; txInfo |= uint256(uint160(srcSender_)) << 32; txInfo |= uint256(srcChainId_) << 192; } function decodeTxInfo(uint256 txInfo_) internal pure returns (uint8 txType, uint8 callbackType, uint8 multi, uint8 registryId, address srcSender, uint64 srcChainId) { txType = uint8(txInfo_); callbackType = uint8(txInfo_ >> 8); multi = uint8(txInfo_ >> 16); registryId = uint8(txInfo_ >> 24); srcSender = address(uint160(txInfo_ >> 32)); srcChainId = uint64(txInfo_ >> 192); } /// @dev returns the vault-form-chain pair of a superform /// @param superformId_ is the id of the superform /// @return superform_ is the address of the superform /// @return formImplementationId_ is the form id /// @return chainId_ is the chain id function getSuperform(uint256 superformId_) internal pure returns (address superform_, uint32 formImplementationId_, uint64 chainId_) { superform_ = address(uint160(superformId_)); formImplementationId_ = uint32(superformId_ >> 160); chainId_ = uint64(superformId_ >> 192); if (chainId_ == 0) { revert Error.INVALID_CHAIN_ID(); } } /// @dev returns the vault-form-chain pair of an array of superforms /// @param superformIds_ array of superforms /// @return superforms_ are the address of the vaults function getSuperforms(uint256[] memory superformIds_) internal pure returns (address[] memory superforms_) { uint256 len = superformIds_.length; superforms_ = new address[](len); for (uint256 i; i < len; ++i) { (superforms_[i],,) = getSuperform(superformIds_[i]); } } /// @dev returns the destination chain of a given superform /// @param superformId_ is the id of the superform /// @return chainId_ is the chain id function getDestinationChain(uint256 superformId_) internal pure returns (uint64 chainId_) { chainId_ = uint64(superformId_ >> 192); if (chainId_ == 0) { revert Error.INVALID_CHAIN_ID(); } } /// @dev generates the superformId /// @param superform_ is the address of the superform /// @param formImplementationId_ is the type of the form /// @param chainId_ is the chain id on which the superform is deployed function packSuperform( address superform_, uint32 formImplementationId_, uint64 chainId_ ) internal pure returns (uint256 superformId_) { superformId_ = uint256(uint160(superform_)); superformId_ |= uint256(formImplementationId_) << 160; superformId_ |= uint256(chainId_) << 192; } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; import { AMBMessage } from "src/types/DataTypes.sol"; /// @dev generates proof for amb message and bytes encoded message library ProofLib { function computeProof(AMBMessage memory message_) internal pure returns (bytes32) { return keccak256(abi.encode(message_)); } function computeProofBytes(AMBMessage memory message_) internal pure returns (bytes memory) { return abi.encode(keccak256(abi.encode(message_))); } function computeProof(bytes memory message_) internal pure returns (bytes32) { return keccak256(message_); } function computeProofBytes(bytes memory message_) internal pure returns (bytes memory) { return abi.encode(keccak256(message_)); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; import { InitSingleVaultData, InitMultiVaultData, LiqRequest } from "src/types/DataTypes.sol"; /// @dev library to cast single values into array for streamlining helper functions /// @notice not gas optimized, suggested for usage only in view/pure functions library ArrayCastLib { function castLiqRequestToArray(LiqRequest memory value_) internal pure returns (LiqRequest[] memory values) { values = new LiqRequest[](1); values[0] = value_; } function castBoolToArray(bool value_) internal pure returns (bool[] memory values) { values = new bool[](1); values[0] = value_; } function castToMultiVaultData(InitSingleVaultData memory data_) internal pure returns (InitMultiVaultData memory castedData_) { uint256[] memory superformIds = new uint256[](1); superformIds[0] = data_.superformId; uint256[] memory amounts = new uint256[](1); amounts[0] = data_.amount; uint256[] memory outputAmounts = new uint256[](1); outputAmounts[0] = data_.outputAmount; uint256[] memory maxSlippage = new uint256[](1); maxSlippage[0] = data_.maxSlippage; LiqRequest[] memory liqData = new LiqRequest[](1); liqData[0] = data_.liqData; castedData_ = InitMultiVaultData( data_.payloadId, superformIds, amounts, outputAmounts, maxSlippage, liqData, castBoolToArray(data_.hasDstSwap), castBoolToArray(data_.retain4626), data_.receiverAddress, data_.extraFormData ); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; import { DataLib } from "src/libraries/DataLib.sol"; import { Error } from "src/libraries/Error.sol"; import { PayloadState, CallbackType, LiqRequest } from "src/types/DataTypes.sol"; /// @dev library to validate slippage updation library PayloadUpdaterLib { function validateSlippage( uint256 newAmount_, uint256 maxAmount_, uint256 slippage_ ) internal pure returns (bool valid_) { /// @dev args validation if (newAmount_ > maxAmount_) { revert Error.NEGATIVE_SLIPPAGE(); } uint256 minAmount = (maxAmount_ * (10_000 - slippage_)) / 10_000; /// @dev amount must fall within the slippage bounds if (newAmount_ < minAmount) { return false; } return true; } function validateLiqReq(LiqRequest memory req_) internal pure { /// revert if token is address(0) -> user wants settlement without any liq data /// revert if token is not address(0) and txData is already present if (req_.token == address(0) || req_.txData.length != 0) { revert Error.CANNOT_UPDATE_WITHDRAW_TX_DATA(); } } function validatePayloadUpdate( uint256 txInfo_, uint8 txType_, PayloadState currentPayloadState_, uint8 isMulti_ ) internal pure { (uint256 txType, uint256 callbackType, uint8 multi,,,) = DataLib.decodeTxInfo(txInfo_); if (!(txType == txType_ && callbackType == uint256(CallbackType.INIT))) { revert Error.INVALID_PAYLOAD_UPDATE_REQUEST(); } if (currentPayloadState_ != PayloadState.STORED) { revert Error.PAYLOAD_ALREADY_UPDATED(); } if (multi != isMulti_) { revert Error.INVALID_PAYLOAD_UPDATE_REQUEST(); } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; library Error { ////////////////////////////////////////////////////////////// // CONFIGURATION ERRORS // ////////////////////////////////////////////////////////////// ///@notice errors thrown in protocol setup /// @dev thrown if chain id exceeds max(uint64) error BLOCK_CHAIN_ID_OUT_OF_BOUNDS(); /// @dev thrown if not possible to revoke a role in broadcasting error CANNOT_REVOKE_NON_BROADCASTABLE_ROLES(); /// @dev thrown if not possible to revoke last admin error CANNOT_REVOKE_LAST_ADMIN(); /// @dev thrown if trying to set again pseudo immutables in super registry error DISABLED(); /// @dev thrown if rescue delay is not yet set for a chain error DELAY_NOT_SET(); /// @dev thrown if get native token price estimate in paymentHelper is 0 error INVALID_NATIVE_TOKEN_PRICE(); /// @dev thrown if wormhole refund chain id is not set error REFUND_CHAIN_ID_NOT_SET(); /// @dev thrown if wormhole relayer is not set error RELAYER_NOT_SET(); /// @dev thrown if a role to be revoked is not assigned error ROLE_NOT_ASSIGNED(); ////////////////////////////////////////////////////////////// // AUTHORIZATION ERRORS // ////////////////////////////////////////////////////////////// ///@notice errors thrown if functions cannot be called /// COMMON AUTHORIZATION ERRORS /// --------------------------------------------------------- /// @dev thrown if caller is not address(this), internal call error INVALID_INTERNAL_CALL(); /// @dev thrown if msg.sender is not a valid amb implementation error NOT_AMB_IMPLEMENTATION(); /// @dev thrown if msg.sender is not an allowed broadcaster error NOT_ALLOWED_BROADCASTER(); /// @dev thrown if msg.sender is not broadcast amb implementation error NOT_BROADCAST_AMB_IMPLEMENTATION(); /// @dev thrown if msg.sender is not broadcast state registry error NOT_BROADCAST_REGISTRY(); /// @dev thrown if msg.sender is not core state registry error NOT_CORE_STATE_REGISTRY(); /// @dev thrown if msg.sender is not emergency admin error NOT_EMERGENCY_ADMIN(); /// @dev thrown if msg.sender is not emergency queue error NOT_EMERGENCY_QUEUE(); /// @dev thrown if msg.sender is not minter error NOT_MINTER(); /// @dev thrown if msg.sender is not minter state registry error NOT_MINTER_STATE_REGISTRY_ROLE(); /// @dev thrown if msg.sender is not paymaster error NOT_PAYMASTER(); /// @dev thrown if msg.sender is not payment admin error NOT_PAYMENT_ADMIN(); /// @dev thrown if msg.sender is not protocol admin error NOT_PROTOCOL_ADMIN(); /// @dev thrown if msg.sender is not state registry error NOT_STATE_REGISTRY(); /// @dev thrown if msg.sender is not super registry error NOT_SUPER_REGISTRY(); /// @dev thrown if msg.sender is not superform router error NOT_SUPERFORM_ROUTER(); /// @dev thrown if msg.sender is not a superform error NOT_SUPERFORM(); /// @dev thrown if msg.sender is not superform factory error NOT_SUPERFORM_FACTORY(); /// @dev thrown if msg.sender is not timelock form error NOT_TIMELOCK_SUPERFORM(); /// @dev thrown if msg.sender is not timelock state registry error NOT_TIMELOCK_STATE_REGISTRY(); /// @dev thrown if msg.sender is not user or disputer error NOT_VALID_DISPUTER(); /// @dev thrown if the msg.sender is not privileged caller error NOT_PRIVILEGED_CALLER(bytes32 role); /// STATE REGISTRY AUTHORIZATION ERRORS /// --------------------------------------------------------- /// @dev layerzero adapter specific error, thrown if caller not layerzero endpoint error CALLER_NOT_ENDPOINT(); /// @dev hyperlane adapter specific error, thrown if caller not hyperlane mailbox error CALLER_NOT_MAILBOX(); /// @dev wormhole relayer specific error, thrown if caller not wormhole relayer error CALLER_NOT_RELAYER(); /// @dev thrown if src chain sender is not valid error INVALID_SRC_SENDER(); ////////////////////////////////////////////////////////////// // INPUT VALIDATION ERRORS // ////////////////////////////////////////////////////////////// ///@notice errors thrown if input variables are not valid /// COMMON INPUT VALIDATION ERRORS /// --------------------------------------------------------- /// @dev thrown if there is an array length mismatch error ARRAY_LENGTH_MISMATCH(); /// @dev thrown if payload id does not exist error INVALID_PAYLOAD_ID(); /// @dev error thrown when msg value should be zero in certain payable functions error MSG_VALUE_NOT_ZERO(); /// @dev thrown if amb ids length is 0 error ZERO_AMB_ID_LENGTH(); /// @dev thrown if address input is address 0 error ZERO_ADDRESS(); /// @dev thrown if amount input is 0 error ZERO_AMOUNT(); /// @dev thrown if final token is address 0 error ZERO_FINAL_TOKEN(); /// @dev thrown if value input is 0 error ZERO_INPUT_VALUE(); /// SUPERFORM ROUTER INPUT VALIDATION ERRORS /// --------------------------------------------------------- /// @dev thrown if the vaults data is invalid error INVALID_SUPERFORMS_DATA(); /// @dev thrown if receiver address is not set error RECEIVER_ADDRESS_NOT_SET(); /// SUPERFORM FACTORY INPUT VALIDATION ERRORS /// --------------------------------------------------------- /// @dev thrown if a form is not ERC165 compatible error ERC165_UNSUPPORTED(); /// @dev thrown if a form is not form interface compatible error FORM_INTERFACE_UNSUPPORTED(); /// @dev error thrown if form implementation address already exists error FORM_IMPLEMENTATION_ALREADY_EXISTS(); /// @dev error thrown if form implementation id already exists error FORM_IMPLEMENTATION_ID_ALREADY_EXISTS(); /// @dev thrown if a form does not exist error FORM_DOES_NOT_EXIST(); /// @dev thrown if form id is larger than max uint16 error INVALID_FORM_ID(); /// @dev thrown if superform not on factory error SUPERFORM_ID_NONEXISTENT(); /// @dev thrown if same vault and form implementation is used to create new superform error VAULT_FORM_IMPLEMENTATION_COMBINATION_EXISTS(); /// FORM INPUT VALIDATION ERRORS /// --------------------------------------------------------- /// @dev thrown if in case of no txData, if liqData.token != vault.asset() /// in case of txData, if token output of swap != vault.asset() error DIFFERENT_TOKENS(); /// @dev thrown if the amount in direct withdraw is not correct error DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); /// @dev thrown if the amount in xchain withdraw is not correct error XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST(); /// LIQUIDITY BRIDGE INPUT VALIDATION ERRORS /// --------------------------------------------------------- /// @dev thrown if route id is blacklisted in socket error BLACKLISTED_ROUTE_ID(); /// @dev thrown if route id is not blacklisted in socket error NOT_BLACKLISTED_ROUTE_ID(); /// @dev error thrown when txData selector of lifi bridge is a blacklisted selector error BLACKLISTED_SELECTOR(); /// @dev error thrown when txData selector of lifi bridge is not a blacklisted selector error NOT_BLACKLISTED_SELECTOR(); /// @dev thrown if a certain action of the user is not allowed given the txData provided error INVALID_ACTION(); /// @dev thrown if in deposits, the liqDstChainId doesn't match the stateReq dstChainId error INVALID_DEPOSIT_LIQ_DST_CHAIN_ID(); /// @dev thrown if index is invalid error INVALID_INDEX(); /// @dev thrown if the chain id in the txdata is invalid error INVALID_TXDATA_CHAIN_ID(); /// @dev thrown if the validation of bridge txData fails due to a destination call present error INVALID_TXDATA_NO_DESTINATIONCALL_ALLOWED(); /// @dev thrown if the validation of bridge txData fails due to wrong receiver error INVALID_TXDATA_RECEIVER(); /// @dev thrown if the validation of bridge txData fails due to wrong token error INVALID_TXDATA_TOKEN(); /// @dev thrown if txData is not present (in case of xChain actions) error NO_TXDATA_PRESENT(); /// STATE REGISTRY INPUT VALIDATION ERRORS /// --------------------------------------------------------- /// @dev thrown if payload is being updated with final amounts length different than amounts length error DIFFERENT_PAYLOAD_UPDATE_AMOUNTS_LENGTH(); /// @dev thrown if payload is being updated with tx data length different than liq data length error DIFFERENT_PAYLOAD_UPDATE_TX_DATA_LENGTH(); /// @dev thrown if keeper update final token is different than the vault underlying error INVALID_UPDATE_FINAL_TOKEN(); /// @dev thrown if broadcast finality for wormhole is invalid error INVALID_BROADCAST_FINALITY(); /// @dev thrown if amb id is not valid leading to an address 0 of the implementation error INVALID_BRIDGE_ID(); /// @dev thrown if chain id involved in xchain message is invalid error INVALID_CHAIN_ID(); /// @dev thrown if payload update amount isn't equal to dst swapper amount error INVALID_DST_SWAP_AMOUNT(); /// @dev thrown if message amb and proof amb are the same error INVALID_PROOF_BRIDGE_ID(); /// @dev thrown if order of proof AMBs is incorrect, either duplicated or not incrementing error INVALID_PROOF_BRIDGE_IDS(); /// @dev thrown if rescue data lengths are invalid error INVALID_RESCUE_DATA(); /// @dev thrown if delay is invalid error INVALID_TIMELOCK_DELAY(); /// @dev thrown if amounts being sent in update payload mean a negative slippage error NEGATIVE_SLIPPAGE(); /// @dev thrown if slippage is outside of bounds error SLIPPAGE_OUT_OF_BOUNDS(); /// SUPERPOSITION INPUT VALIDATION ERRORS /// --------------------------------------------------------- /// @dev thrown if src senders mismatch in state sync error SRC_SENDER_MISMATCH(); /// @dev thrown if src tx types mismatch in state sync error SRC_TX_TYPE_MISMATCH(); ////////////////////////////////////////////////////////////// // EXECUTION ERRORS // ////////////////////////////////////////////////////////////// ///@notice errors thrown due to function execution logic /// COMMON EXECUTION ERRORS /// --------------------------------------------------------- /// @dev thrown if the swap in a direct deposit resulted in insufficient tokens error DIRECT_DEPOSIT_SWAP_FAILED(); /// @dev thrown if payload is not unique error DUPLICATE_PAYLOAD(); /// @dev thrown if native tokens fail to be sent to superform contracts error FAILED_TO_SEND_NATIVE(); /// @dev thrown if allowance is not correct to deposit error INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT(); /// @dev thrown if contract has insufficient balance for operations error INSUFFICIENT_BALANCE(); /// @dev thrown if native amount is not at least equal to the amount in the request error INSUFFICIENT_NATIVE_AMOUNT(); /// @dev thrown if payload cannot be decoded error INVALID_PAYLOAD(); /// @dev thrown if payload status is invalid error INVALID_PAYLOAD_STATUS(); /// @dev thrown if payload type is invalid error INVALID_PAYLOAD_TYPE(); /// LIQUIDITY BRIDGE EXECUTION ERRORS /// --------------------------------------------------------- /// @dev thrown if we try to decode the final swap output token in a xChain liquidity bridging action error CANNOT_DECODE_FINAL_SWAP_OUTPUT_TOKEN(); /// @dev thrown if liquidity bridge fails for erc20 or native tokens error FAILED_TO_EXECUTE_TXDATA(address token); /// @dev thrown if asset being used for deposit mismatches in multivault deposits error INVALID_DEPOSIT_TOKEN(); /// STATE REGISTRY EXECUTION ERRORS /// --------------------------------------------------------- /// @dev thrown if bridge tokens haven't arrived to destination error BRIDGE_TOKENS_PENDING(); /// @dev thrown if withdrawal tx data cannot be updated error CANNOT_UPDATE_WITHDRAW_TX_DATA(); /// @dev thrown if rescue passed dispute deadline error DISPUTE_TIME_ELAPSED(); /// @dev thrown if message failed to reach the specified level of quorum needed error INSUFFICIENT_QUORUM(); /// @dev thrown if broadcast payload is invalid error INVALID_BROADCAST_PAYLOAD(); /// @dev thrown if broadcast fee is invalid error INVALID_BROADCAST_FEE(); /// @dev thrown if retry fees is less than required error INVALID_RETRY_FEE(); /// @dev thrown if broadcast message type is wrong error INVALID_MESSAGE_TYPE(); /// @dev thrown if payload hash is invalid during `retryMessage` on Layezero implementation error INVALID_PAYLOAD_HASH(); /// @dev thrown if update payload function was called on a wrong payload error INVALID_PAYLOAD_UPDATE_REQUEST(); /// @dev thrown if a state registry id is 0 error INVALID_REGISTRY_ID(); /// @dev thrown if a form state registry id is 0 error INVALID_FORM_REGISTRY_ID(); /// @dev thrown if trying to finalize the payload but the withdraw is still locked error LOCKED(); /// @dev thrown if payload is already updated (during xChain deposits) error PAYLOAD_ALREADY_UPDATED(); /// @dev thrown if payload is already processed error PAYLOAD_ALREADY_PROCESSED(); /// @dev thrown if payload is not in UPDATED state error PAYLOAD_NOT_UPDATED(); /// @dev thrown if rescue is still in timelocked state error RESCUE_LOCKED(); /// @dev thrown if rescue is already proposed error RESCUE_ALREADY_PROPOSED(); /// @dev thrown if payload hash is zero during `retryMessage` on Layezero implementation error ZERO_PAYLOAD_HASH(); /// DST SWAPPER EXECUTION ERRORS /// --------------------------------------------------------- /// @dev thrown if process dst swap is tried for processed payload id error DST_SWAP_ALREADY_PROCESSED(); /// @dev thrown if indices have duplicates error DUPLICATE_INDEX(); /// @dev thrown if failed dst swap is already updated error FAILED_DST_SWAP_ALREADY_UPDATED(); /// @dev thrown if indices are out of bounds error INDEX_OUT_OF_BOUNDS(); /// @dev thrown if failed swap token amount is 0 error INVALID_DST_SWAPPER_FAILED_SWAP(); /// @dev thrown if failed swap token amount is not 0 and if token balance is less than amount (non zero) error INVALID_DST_SWAPPER_FAILED_SWAP_NO_TOKEN_BALANCE(); /// @dev thrown if failed swap token amount is not 0 and if native amount is less than amount (non zero) error INVALID_DST_SWAPPER_FAILED_SWAP_NO_NATIVE_BALANCE(); /// @dev forbid xChain deposits with destination swaps without interim token set (for user protection) error INVALID_INTERIM_TOKEN(); /// @dev thrown if dst swap output is less than minimum expected error INVALID_SWAP_OUTPUT(); /// FORM EXECUTION ERRORS /// --------------------------------------------------------- /// @dev thrown if try to forward 4626 share from the superform error CANNOT_FORWARD_4646_TOKEN(); /// @dev thrown in KYCDAO form if no KYC token is present error NO_VALID_KYC_TOKEN(); /// @dev thrown in forms where a certain functionality is not allowed or implemented error NOT_IMPLEMENTED(); /// @dev thrown if form implementation is PAUSED, users cannot perform any action error PAUSED(); /// @dev thrown if shares != deposit output or assets != redeem output when minting SuperPositions error VAULT_IMPLEMENTATION_FAILED(); /// @dev thrown if withdrawal tx data is not updated error WITHDRAW_TOKEN_NOT_UPDATED(); /// @dev thrown if withdrawal tx data is not updated error WITHDRAW_TX_DATA_NOT_UPDATED(); /// @dev thrown when redeeming from vault yields zero collateral error WITHDRAW_ZERO_COLLATERAL(); /// PAYMENT HELPER EXECUTION ERRORS /// --------------------------------------------------------- /// @dev thrown if chainlink is reporting an improper price error CHAINLINK_MALFUNCTION(); /// @dev thrown if chainlink is reporting an incomplete round error CHAINLINK_INCOMPLETE_ROUND(); /// @dev thrown if feed decimals is not 8 error CHAINLINK_UNSUPPORTED_DECIMAL(); /// EMERGENCY QUEUE EXECUTION ERRORS /// --------------------------------------------------------- /// @dev thrown if emergency withdraw is not queued error EMERGENCY_WITHDRAW_NOT_QUEUED(); /// @dev thrown if emergency withdraw is already processed error EMERGENCY_WITHDRAW_PROCESSED_ALREADY(); /// SUPERPOSITION EXECUTION ERRORS /// --------------------------------------------------------- /// @dev thrown if uri cannot be updated error DYNAMIC_URI_FROZEN(); /// @dev thrown if tx history is not found while state sync error TX_HISTORY_NOT_FOUND(); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; /// @dev contains all the common struct and enums used for data communication between chains. /// @dev There are two transaction types in Superform Protocol enum TransactionType { DEPOSIT, WITHDRAW } /// @dev Message types can be INIT, RETURN (for successful Deposits) and FAIL (for failed withdraws) enum CallbackType { INIT, RETURN, FAIL } /// @dev Payloads are stored, updated (deposits) or processed (finalized) enum PayloadState { STORED, UPDATED, PROCESSED } /// @dev contains all the common struct used for interchain token transfers. struct LiqRequest { /// @dev generated data bytes txData; /// @dev input token for deposits, desired output token on target liqDstChainId for withdraws. Must be set for /// txData to be updated on destination for withdraws address token; /// @dev intermediary token on destination. Relevant for xChain deposits where a destination swap is needed for /// validation purposes address interimToken; /// @dev what bridge to use to move tokens uint8 bridgeId; /// @dev dstChainId = liqDstchainId for deposits. For withdraws it is the target chain id for where the underlying /// is to be delivered uint64 liqDstChainId; /// @dev currently this amount is used as msg.value in the txData call. uint256 nativeAmount; } /// @dev main struct that holds required multi vault data for an action struct MultiVaultSFData { // superformids must have same destination. Can have different underlyings uint256[] superformIds; uint256[] amounts; // on deposits, amount of token to deposit on dst, on withdrawals, superpositions to burn uint256[] outputAmounts; // on deposits, amount of shares to receive, on withdrawals, amount of assets to receive uint256[] maxSlippages; LiqRequest[] liqRequests; // if length = 1; amount = sum(amounts) | else amounts must match the amounts being sent bytes permit2data; bool[] hasDstSwaps; bool[] retain4626s; // if true, we don't mint SuperPositions, and send the 4626 back to the user instead address receiverAddress; /// this address must always be an EOA otherwise funds may be lost address receiverAddressSP; /// this address can be a EOA or a contract that implements onERC1155Receiver. must always be set for deposits bytes extraFormData; // extraFormData } /// @dev main struct that holds required single vault data for an action struct SingleVaultSFData { // superformids must have same destination. Can have different underlyings uint256 superformId; uint256 amount; uint256 outputAmount; // on deposits, amount of shares to receive, on withdrawals, amount of assets to receive uint256 maxSlippage; LiqRequest liqRequest; // if length = 1; amount = sum(amounts)| else amounts must match the amounts being sent bytes permit2data; bool hasDstSwap; bool retain4626; // if true, we don't mint SuperPositions, and send the 4626 back to the user instead address receiverAddress; /// this address must always be an EOA otherwise funds may be lost address receiverAddressSP; /// this address can be a EOA or a contract that implements onERC1155Receiver. must always be set for deposits bytes extraFormData; // extraFormData } /// @dev overarching struct for multiDst requests with multi vaults struct MultiDstMultiVaultStateReq { uint8[][] ambIds; uint64[] dstChainIds; MultiVaultSFData[] superformsData; } /// @dev overarching struct for single cross chain requests with multi vaults struct SingleXChainMultiVaultStateReq { uint8[] ambIds; uint64 dstChainId; MultiVaultSFData superformsData; } /// @dev overarching struct for multiDst requests with single vaults struct MultiDstSingleVaultStateReq { uint8[][] ambIds; uint64[] dstChainIds; SingleVaultSFData[] superformsData; } /// @dev overarching struct for single cross chain requests with single vaults struct SingleXChainSingleVaultStateReq { uint8[] ambIds; uint64 dstChainId; SingleVaultSFData superformData; } /// @dev overarching struct for single direct chain requests with single vaults struct SingleDirectSingleVaultStateReq { SingleVaultSFData superformData; } /// @dev overarching struct for single direct chain requests with multi vaults struct SingleDirectMultiVaultStateReq { MultiVaultSFData superformData; } /// @dev struct for SuperRouter with re-arranged data for the message (contains the payloadId) /// @dev realize that receiverAddressSP is not passed, only needed on source chain to mint struct InitMultiVaultData { uint256 payloadId; uint256[] superformIds; uint256[] amounts; uint256[] outputAmounts; uint256[] maxSlippages; LiqRequest[] liqData; bool[] hasDstSwaps; bool[] retain4626s; address receiverAddress; bytes extraFormData; } /// @dev struct for SuperRouter with re-arranged data for the message (contains the payloadId) struct InitSingleVaultData { uint256 payloadId; uint256 superformId; uint256 amount; uint256 outputAmount; uint256 maxSlippage; LiqRequest liqData; bool hasDstSwap; bool retain4626; address receiverAddress; bytes extraFormData; } /// @dev struct for Emergency Queue struct QueuedWithdrawal { address receiverAddress; uint256 superformId; uint256 amount; uint256 srcPayloadId; bool isProcessed; } /// @dev all statuses of the timelock payload enum TimelockStatus { UNAVAILABLE, PENDING, PROCESSED } /// @dev holds information about the timelock payload struct TimelockPayload { uint8 isXChain; uint64 srcChainId; uint256 lockedTill; InitSingleVaultData data; TimelockStatus status; } /// @dev struct that contains the type of transaction, callback flags and other identification, as well as the vaults /// data in params struct AMBMessage { uint256 txInfo; // tight packing of TransactionType txType, CallbackType flag if multi/single vault, registry id, // srcSender and srcChainId bytes params; // decoding txInfo will point to the right datatype of params. Refer PayloadHelper.sol } /// @dev struct that contains the information required for broadcasting changes struct BroadcastMessage { bytes target; bytes32 messageType; bytes message; } /// @dev struct that contains info on returned data from destination struct ReturnMultiData { uint256 payloadId; uint256[] superformIds; uint256[] amounts; } /// @dev struct that contains info on returned data from destination struct ReturnSingleData { uint256 payloadId; uint256 superformId; uint256 amount; } /// @dev struct that contains the data on the fees to pay to the AMBs struct AMBExtraData { uint256[] gasPerAMB; bytes[] extraDataPerAMB; } /// @dev struct that contains the data on the fees to pay to the AMBs on broadcasts struct BroadCastAMBExtraData { uint256[] gasPerDst; bytes[] extraDataPerDst; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC-20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC-20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; import { PayloadState } from "src/types/DataTypes.sol"; /// @title IBaseStateRegistry /// @dev Interface for BaseStateRegistry /// @author ZeroPoint Labs interface IBaseStateRegistry { ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// /// @dev is emitted when a cross-chain payload is received in the state registry event PayloadReceived(uint64 indexed srcChainId, uint64 indexed dstChainId, uint256 indexed payloadId); /// @dev is emitted when a cross-chain proof is received in the state registry /// NOTE: comes handy if quorum required is more than 0 event ProofReceived(bytes32 indexed proof); /// @dev is emitted when a payload id gets updated event PayloadUpdated(uint256 indexed payloadId); /// @dev is emitted when a payload id gets processed event PayloadProcessed(uint256 indexed payloadId); /// @dev is emitted when the super registry address is updated event SuperRegistryUpdated(address indexed superRegistry); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// /// @dev allows users to read the total payloads received by the registry function payloadsCount() external view returns (uint256); /// @dev allows user to read the payload state /// uint256 payloadId_ is the unique payload identifier allocated on the destination chain function payloadTracking(uint256 payloadId_) external view returns (PayloadState payloadState_); /// @dev allows users to read the bytes payload_ stored per payloadId_ /// @param payloadId_ is the unique payload identifier allocated on the destination chain /// @return payloadBody_ the crosschain data received function payloadBody(uint256 payloadId_) external view returns (bytes memory payloadBody_); /// @dev allows users to read the uint256 payloadHeader stored per payloadId_ /// @param payloadId_ is the unique payload identifier allocated on the destination chain /// @return payloadHeader_ the crosschain header received function payloadHeader(uint256 payloadId_) external view returns (uint256 payloadHeader_); /// @dev allows users to read the ambs that delivered the payload id /// @param payloadId_ is the unique payload identifier allocated on the destination chain /// @return ambIds_ is the identifier of ambs that delivered the message and proof function getMessageAMB(uint256 payloadId_) external view returns (uint8[] memory ambIds_); ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// /// @dev allows core contracts to send payload to a destination chain. /// @param srcSender_ is the caller of the function (used for gas refunds). /// @param ambIds_ is the identifier of the arbitrary message bridge to be used /// @param dstChainId_ is the internal chainId used throughout the protocol /// @param message_ is the crosschain payload to be sent /// @param extraData_ defines all the message bridge related overrides /// NOTE: dstChainId_ is mapped to message bridge's destination id inside it's implementation contract /// NOTE: ambIds_ are superform assigned unique identifier for arbitrary message bridges function dispatchPayload( address srcSender_, uint8[] memory ambIds_, uint64 dstChainId_, bytes memory message_, bytes memory extraData_ ) external payable; /// @dev allows state registry to receive messages from message bridge implementations /// @param srcChainId_ is the superform chainId from which the payload is dispatched/sent /// @param message_ is the crosschain payload received /// NOTE: Only {IMPLEMENTATION_CONTRACT} role can call this function. function receivePayload(uint64 srcChainId_, bytes memory message_) external; /// @dev allows privileged actors to process cross-chain payloads /// @param payloadId_ is the identifier of the cross-chain payload /// NOTE: Only {CORE_STATE_REGISTRY_PROCESSOR_ROLE} role can call this function /// NOTE: this should handle reverting the state on source chain in-case of failure /// (or) can implement scenario based reverting like in coreStateRegistry function processPayload(uint256 payloadId_) external payable; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; /// @title IAmbImplementation /// @dev Interface for arbitrary message bridge (AMB) implementations /// @author ZeroPoint Labs interface IAmbImplementation { ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// event ChainAdded(uint64 indexed superChainId); event AuthorizedImplAdded(uint64 indexed superChainId, address indexed authImpl); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// /// @dev returns the gas fees estimation in native tokens /// @notice not all AMBs will have on-chain estimation for which this function will return 0 /// @param dstChainId_ is the identifier of the destination chain /// @param message_ is the cross-chain message /// @param extraData_ is any amb-specific information /// @return fees is the native_tokens to be sent along the transaction function estimateFees( uint64 dstChainId_, bytes memory message_, bytes memory extraData_ ) external view returns (uint256 fees); /// @dev returns the extra data for the given gas request /// @param gasLimit is the amount of gas limit in wei to override /// @return extraData is the bytes encoded extra data /// NOTE: this process is unique to the message bridge function generateExtraData(uint256 gasLimit) external pure returns (bytes memory extraData); ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// /// @dev allows state registry to send message via implementation. /// @param srcSender_ is the caller (used for gas refunds) /// @param dstChainId_ is the identifier of the destination chain /// @param message_ is the cross-chain message to be sent /// @param extraData_ is message amb specific override information function dispatchPayload( address srcSender_, uint64 dstChainId_, bytes memory message_, bytes memory extraData_ ) external payable; /// @dev allows for the permissionless calling of the retry mechanism for encoded data /// @param data_ is the encoded retry data (different per AMB implementation) function retryPayload(bytes memory data_) external payable; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; /// @title IQuorumManager /// @dev Interface for QuorumManager /// @author ZeroPoint Labs interface IQuorumManager { ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// /// @dev emitted when a new quorum is set for a specific chain /// @param srcChainId the chain id from which the message (payload) is sent /// @param quorum the minimum number of message bridges required for processing event QuorumSet(uint64 indexed srcChainId, uint256 indexed quorum); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// /// @dev returns the required quorum for the srcChain & dstChain /// @param srcChainId_ is the chain id from which the message (payload) is sent /// @return quorum_ the minimum number of message bridges required for processing function getRequiredMessagingQuorum(uint64 srcChainId_) external view returns (uint256 quorum_); ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// /// @dev allows inheriting contracts to set the messaging quorum for a specific sender chain /// @notice quorum is the number of extra ambs a message proof must go through and be validated /// @param srcChainId_ is the chain id from which the message (payload) is sent /// @param quorum_ the minimum number of message bridges required for processing /// NOTE: overriding child contracts should handle the sender validation & setting of message quorum function setRequiredMessagingQuorum(uint64 srcChainId_, uint256 quorum_) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC4626.sol) pragma solidity ^0.8.20; import {IERC20} from "../token/ERC20/IERC20.sol"; import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol"; /** * @dev Interface of the ERC-4626 "Tokenized Vault Standard", as defined in * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626]. */ interface IERC4626 is IERC20, IERC20Metadata { event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares); event Withdraw( address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares ); /** * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing. * * - MUST be an ERC-20 token contract. * - MUST NOT revert. */ function asset() external view returns (address assetTokenAddress); /** * @dev Returns the total amount of the underlying asset that is “managed” by Vault. * * - SHOULD include any compounding that occurs from yield. * - MUST be inclusive of any fees that are charged against assets in the Vault. * - MUST NOT revert. */ function totalAssets() external view returns (uint256 totalManagedAssets); /** * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal * scenario where all the conditions are met. * * - MUST NOT be inclusive of any fees that are charged against assets in the Vault. * - MUST NOT show any variations depending on the caller. * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. * - MUST NOT revert. * * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and * from. */ function convertToShares(uint256 assets) external view returns (uint256 shares); /** * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal * scenario where all the conditions are met. * * - MUST NOT be inclusive of any fees that are charged against assets in the Vault. * - MUST NOT show any variations depending on the caller. * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. * - MUST NOT revert. * * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and * from. */ function convertToAssets(uint256 shares) external view returns (uint256 assets); /** * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver, * through a deposit call. * * - MUST return a limited value if receiver is subject to some deposit limit. * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited. * - MUST NOT revert. */ function maxDeposit(address receiver) external view returns (uint256 maxAssets); /** * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given * current on-chain conditions. * * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit * call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called * in the same transaction. * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the * deposit would be accepted, regardless if the user has enough tokens approved, etc. * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees. * - MUST NOT revert. * * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in * share price or some other type of condition, meaning the depositor will lose assets by depositing. */ function previewDeposit(uint256 assets) external view returns (uint256 shares); /** * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens. * * - MUST emit the Deposit event. * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the * deposit execution, and are accounted for during deposit. * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not * approving enough underlying tokens to the Vault contract, etc). * * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token. */ function deposit(uint256 assets, address receiver) external returns (uint256 shares); /** * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call. * - MUST return a limited value if receiver is subject to some mint limit. * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted. * - MUST NOT revert. */ function maxMint(address receiver) external view returns (uint256 maxShares); /** * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given * current on-chain conditions. * * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call * in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the * same transaction. * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint * would be accepted, regardless if the user has enough tokens approved, etc. * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees. * - MUST NOT revert. * * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in * share price or some other type of condition, meaning the depositor will lose assets by minting. */ function previewMint(uint256 shares) external view returns (uint256 assets); /** * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens. * * - MUST emit the Deposit event. * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint * execution, and are accounted for during mint. * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not * approving enough underlying tokens to the Vault contract, etc). * * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token. */ function mint(uint256 shares, address receiver) external returns (uint256 assets); /** * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the * Vault, through a withdraw call. * * - MUST return a limited value if owner is subject to some withdrawal limit or timelock. * - MUST NOT revert. */ function maxWithdraw(address owner) external view returns (uint256 maxAssets); /** * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block, * given current on-chain conditions. * * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw * call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if * called * in the same transaction. * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though * the withdrawal would be accepted, regardless if the user has enough shares, etc. * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees. * - MUST NOT revert. * * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in * share price or some other type of condition, meaning the depositor will lose assets by depositing. */ function previewWithdraw(uint256 assets) external view returns (uint256 shares); /** * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver. * * - MUST emit the Withdraw event. * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the * withdraw execution, and are accounted for during withdraw. * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner * not having enough shares, etc). * * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed. * Those methods should be performed separately. */ function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares); /** * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault, * through a redeem call. * * - MUST return a limited value if owner is subject to some withdrawal limit or timelock. * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock. * - MUST NOT revert. */ function maxRedeem(address owner) external view returns (uint256 maxShares); /** * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block, * given current on-chain conditions. * * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call * in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the * same transaction. * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the * redemption would be accepted, regardless if the user has enough shares, etc. * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees. * - MUST NOT revert. * * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in * share price or some other type of condition, meaning the depositor will lose assets by redeeming. */ function previewRedeem(uint256 shares) external view returns (uint256 assets); /** * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver. * * - MUST emit the Withdraw event. * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the * redeem execution, and are accounted for during redeem. * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner * not having enough shares, etc). * * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed. * Those methods should be performed separately. */ function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @dev External interface of AccessControl declared to support ERC-165 detection. */ interface IAccessControl { /** * @dev The `account` is missing a role. */ error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); /** * @dev The caller of a function is not the expected one. * * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. */ error AccessControlBadConfirmation(); /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. */ function renounceRole(bytes32 role, address callerConfirmation) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import { IERC1155 } from "openzeppelin-contracts/contracts/token/ERC1155/IERC1155.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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612]. * * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC-20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.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 { /** * @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; }
{ "remappings": [ "solmate/=lib/ERC1155A/lib/solmate/src/", "ERC1155A/=lib/ERC1155A/src/", "@openzeppelin/contracts/=lib/ERC1155A/lib/openzeppelin-contracts/contracts/", "ds-test/=lib/ds-test/src/", "erc4626-tests/=lib/ERC1155A/lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts/=lib/ERC1155A/lib/openzeppelin-contracts/", "pigeon/=lib/pigeon/src/", "solady/=lib/pigeon/lib/solady/", "super-vaults/=lib/super-vaults/src/", "v2-core/=lib/super-vaults/lib/v2-core/contracts/", "v2-periphery/=lib/super-vaults/lib/v2-periphery/contracts/", "v3-core/=lib/super-vaults/lib/v3-core/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract ISuperRegistry","name":"superRegistry_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"BLOCK_CHAIN_ID_OUT_OF_BOUNDS","type":"error"},{"inputs":[],"name":"BRIDGE_TOKENS_PENDING","type":"error"},{"inputs":[],"name":"CANNOT_UPDATE_WITHDRAW_TX_DATA","type":"error"},{"inputs":[],"name":"DELAY_NOT_SET","type":"error"},{"inputs":[],"name":"DIFFERENT_PAYLOAD_UPDATE_AMOUNTS_LENGTH","type":"error"},{"inputs":[],"name":"DIFFERENT_PAYLOAD_UPDATE_TX_DATA_LENGTH","type":"error"},{"inputs":[],"name":"DISPUTE_TIME_ELAPSED","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"INSUFFICIENT_QUORUM","type":"error"},{"inputs":[],"name":"INVALID_CHAIN_ID","type":"error"},{"inputs":[],"name":"INVALID_DST_SWAP_AMOUNT","type":"error"},{"inputs":[],"name":"INVALID_INTERNAL_CALL","type":"error"},{"inputs":[],"name":"INVALID_PAYLOAD_ID","type":"error"},{"inputs":[],"name":"INVALID_PAYLOAD_TYPE","type":"error"},{"inputs":[],"name":"INVALID_PAYLOAD_UPDATE_REQUEST","type":"error"},{"inputs":[],"name":"INVALID_PROOF_BRIDGE_ID","type":"error"},{"inputs":[],"name":"INVALID_PROOF_BRIDGE_IDS","type":"error"},{"inputs":[],"name":"INVALID_RESCUE_DATA","type":"error"},{"inputs":[],"name":"INVALID_UPDATE_FINAL_TOKEN","type":"error"},{"inputs":[],"name":"NEGATIVE_SLIPPAGE","type":"error"},{"inputs":[],"name":"NOT_AMB_IMPLEMENTATION","type":"error"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"NOT_PRIVILEGED_CALLER","type":"error"},{"inputs":[],"name":"NOT_SUPERFORM_ROUTER","type":"error"},{"inputs":[],"name":"NOT_VALID_DISPUTER","type":"error"},{"inputs":[],"name":"PAYLOAD_ALREADY_PROCESSED","type":"error"},{"inputs":[],"name":"PAYLOAD_ALREADY_UPDATED","type":"error"},{"inputs":[],"name":"PAYLOAD_NOT_UPDATED","type":"error"},{"inputs":[],"name":"RESCUE_ALREADY_PROPOSED","type":"error"},{"inputs":[],"name":"RESCUE_LOCKED","type":"error"},{"inputs":[],"name":"SLIPPAGE_OUT_OF_BOUNDS","type":"error"},{"inputs":[],"name":"SUPERFORM_ID_NONEXISTENT","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"currentAllowance","type":"uint256"},{"internalType":"uint256","name":"requestedDecrease","type":"uint256"}],"name":"SafeERC20FailedDecreaseAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"ZERO_AMB_ID_LENGTH","type":"error"},{"inputs":[],"name":"ZERO_AMOUNT","type":"error"},{"inputs":[],"name":"ZERO_FINAL_TOKEN","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"payloadId","type":"uint256"}],"name":"FailedXChainDeposits","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"payloadId","type":"uint256"}],"name":"PayloadProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"srcChainId","type":"uint64"},{"indexed":true,"internalType":"uint64","name":"dstChainId","type":"uint64"},{"indexed":true,"internalType":"uint256","name":"payloadId","type":"uint256"}],"name":"PayloadReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"payloadId","type":"uint256"}],"name":"PayloadUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"proof","type":"bytes32"}],"name":"ProofReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"payloadId","type":"uint256"}],"name":"RescueDisputed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"payloadId","type":"uint256"}],"name":"RescueFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"payloadId","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"superformIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"proposedAmount","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"proposedTime","type":"uint256"}],"name":"RescueProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"superRegistry","type":"address"}],"name":"SuperRegistryUpdated","type":"event"},{"inputs":[],"name":"CHAIN_ID","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"srcSender_","type":"address"},{"internalType":"uint8[]","name":"ambIds_","type":"uint8[]"},{"internalType":"uint64","name":"dstChainId_","type":"uint64"},{"internalType":"bytes","name":"message_","type":"bytes"},{"internalType":"bytes","name":"extraData_","type":"bytes"}],"name":"dispatchPayload","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"payloadId_","type":"uint256"}],"name":"disputeRescueFailedDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"payloadId_","type":"uint256"}],"name":"finalizeRescueFailedDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"payloadId_","type":"uint256"}],"name":"getFailedDeposits","outputs":[{"internalType":"uint256[]","name":"superformIds","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256","name":"lastProposedTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"payloadId_","type":"uint256"}],"name":"getMessageAMB","outputs":[{"internalType":"uint8[]","name":"","type":"uint8[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"messageQuorum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"payloadBody","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"payloadHeader","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"payloadTracking","outputs":[{"internalType":"enum PayloadState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"payloadsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"payloadId_","type":"uint256"}],"name":"processPayload","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"payloadId_","type":"uint256"},{"internalType":"uint256[]","name":"proposedAmounts_","type":"uint256[]"}],"name":"proposeRescueFailedDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"srcChainId_","type":"uint64"},{"internalType":"bytes","name":"message_","type":"bytes"}],"name":"receivePayload","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"superRegistry","outputs":[{"internalType":"contract ISuperRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"payloadId_","type":"uint256"},{"internalType":"address[]","name":"finalTokens_","type":"address[]"},{"internalType":"uint256[]","name":"finalAmounts_","type":"uint256[]"}],"name":"updateDepositPayload","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"payloadId_","type":"uint256"},{"internalType":"bytes[]","name":"txData_","type":"bytes[]"}],"name":"updateWithdrawPayload","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"finalAmount_","type":"uint256"},{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"uint256","name":"maxSlippage_","type":"uint256"}],"name":"validateSlippage","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60c06040523480156200001157600080fd5b506040516200610d3803806200610d83398101604081905262000034916200007e565b806001600160401b034611156200005e57604051637ecdf93360e01b815260040160405180910390fd5b6001600160401b03461660a0526001600160a01b031660805250620000b0565b6000602082840312156200009157600080fd5b81516001600160a01b0381168114620000a957600080fd5b9392505050565b60805160a051615ff16200011c600039600081816102c70152818161100c01528181611d050152613f6f01526000818161017e01528181610e6b0152818161153d015281816115fe01528181613262015281816136ce0152818161432601526143d80152615ff16000f3fe6080604052600436106101095760003560e01c80635aef948011610095578063cc2d8abd11610064578063cc2d8abd1461033e578063d468711a1461035e578063d49616061461038d578063d830364e146103ba578063e17d89e8146103e757600080fd5b80635aef948014610272578063803c15df1461028557806385e1f4d0146102b5578063b63d36a51461030157600080fd5b80632d46647d116100dc5780632d46647d146101b8578063361ad42b146101d857806336445ffd14610205578063439890e214610232578063474fd8741461025257600080fd5b806313bff0121461010e57806313c02a591461013057806323de31e11461015957806324c73dda1461016c575b600080fd5b34801561011a57600080fd5b5061012e610129366004614a13565b610407565b005b34801561013c57600080fd5b5061014660005481565b6040519081526020015b60405180910390f35b61012e610167366004614ba1565b6104fe565b34801561017857600080fd5b506101a07f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610150565b3480156101c457600080fd5b5061012e6101d3366004614a13565b61056c565b3480156101e457600080fd5b506101f86101f3366004614a13565b610815565b6040516101509190614cfd565b34801561021157600080fd5b50610146610220366004614a13565b60026020526000908152604090205481565b34801561023e57600080fd5b5061012e61024d366004614d5b565b6108af565b34801561025e57600080fd5b5061012e61026d366004614da6565b610980565b61012e610280366004614a13565b610afb565b34801561029157600080fd5b506102a56102a0366004614e1f565b610e1f565b6040519015158152602001610150565b3480156102c157600080fd5b506102e97f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160401b039091168152602001610150565b34801561030d57600080fd5b5061033161031c366004614a13565b60046020526000908152604090205460ff1681565b6040516101509190614e61565b34801561034a57600080fd5b5061012e610359366004614e89565b610e56565b34801561036a57600080fd5b5061037e610379366004614a13565b611070565b60405161015093929190614f14565b34801561039957600080fd5b506101466103a8366004614a13565b60036020526000908152604090205481565b3480156103c657600080fd5b506103da6103d5366004614a13565b611136565b6040516101509190614f7e565b3480156103f357600080fd5b5061012e610402366004614d5b565b6111b6565b6104108161146b565b600081815260066020526040902060048101546001600160a01b031633148061045e575061045e7f3c98683c4fc1f07b3a173ce23e8e5b9ee147da7d8df6f5e0da4c07c15e354a0733611491565b61047b57604051630363e30760e61b815260040160405180910390fd5b600581015415806104a1575061048f611538565b816005015461049e9190614fa7565b42115b156104bf576040516360387b3360e01b815260040160405180910390fd5b6000828152600660205260408082206005018290555183917f7e98ef42b90939b396b85416fa66b14f7a5c284f7a7e794d995b3fad3c6e85cb91a25050565b6105277f3a2f5529773e03d975be44bdae98a8509bdf1159e407504e558536cde56cf6ac6115e5565b6001600160a01b0316336001600160a01b0316146105585760405163158a2f6b60e01b815260040160405180910390fd5b6105658585858585611672565b5050505050565b6105758161146b565b6000818152600660205260409020600581015415806105aa5750610597611538565b81600501546105a69190614fa7565b4211155b156105c857604051633527c42560e01b815260040160405180910390fd5b6000600582018190556002820154905b81811015610787578260030181815481106105f5576105f5614fba565b90600052602060002090602091828204019190069054906101000a900460ff1615610719576106437f494dfdc880823954ed6700117eb435b9bca3643417437b5781c1a89fba6e8b976115e5565b60048401546001850180546001600160a01b03938416936310d7d359931691908590811061067357610673614fba565b6000918252602090912001546002870180546001600160a01b0390921691869081106106a1576106a1614fba565b6000918252602090912001546040516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b1580156106fc57600080fd5b505af1158015610710573d6000803e3d6000fd5b5050505061077f565b600483015460028401805461077f926001600160a01b031691908490811061074357610743614fba565b906000526020600020015485600101848154811061076357610763614fba565b6000918252602090912001546001600160a01b03169190611a12565b6001016105d8565b506000838152600660205260408120906107a182826147ee565b6107af6001830160006147ee565b6107bd6002830160006147ee565b6107cb60038301600061480c565b506004810180546001600160a01b03191690556000600590910181905560405184917f4dcd0d064503785f7194bc0d094f808cd1df65b1440424e51cd211c9672f77cc91a2505050565b6001602052600090815260409020805461082e90614fd0565b80601f016020809104026020016040519081016040528092919081815260200182805461085a90614fd0565b80156108a75780601f1061087c576101008083540402835291602001916108a7565b820191906000526020600020905b81548152906001019060200180831161088a57829003601f168201915b505050505081565b6108d87f67ae681a1ce853cc4fa2ec7bd45049225042d6a828b9865aca9ef1218a52bcfc611a71565b6108e18361146b565b60008060008060006108f288611aa0565b985050509650505094509450945061092e8560018081111561091657610916614e4b565b60008b81526004602052604090205460ff1685611bdd565b61093b8482898986611c7d565b935061094b888486886001611db5565b60405188907f144d814d5dc6f17c1a88bc42c55d67392a51c818908ed7cca6118bc51a34b15390600090a25050505050505050565b6109a97f67ae681a1ce853cc4fa2ec7bd45049225042d6a828b9865aca9ef1218a52bcfc611a71565b6109b28561146b565b6000806000806109c189611aa0565b505050955050509350935093506109fd84600060018111156109e5576109e5614e4b565b60008c81526004602052604090205460ff1684611bdd565b600060ff821615610a2057610a168a8589898d8d611e79565b9094509050610a72565b610a6c8a8589896000818110610a3857610a38614fba565b905060200201358c8c6000818110610a5257610a52614fba565b9050602002016020810190610a67919061500a565b6123e6565b90945090505b610a7f8a84868885611db5565b6002816002811115610a9357610a93614e4b565b03610aef576040518a907fbce0bd6fef1367dca0b65255a7d010501f79e4dd96d4add4c3e42a419ae6457c90600090a26040518a907f21c4f33a94342256a428d6cb08476047bdb16e6866308b7d904df8990eb781c890600090a25b50505050505050505050565b610b247ff7c2c1de3464c8fee0ad8a71a80d665aeafd6a725243593923472fe5e76e45b1611a71565b610b2d8161146b565b600260008281526004602052604090205460ff166002811115610b5257610b52614e4b565b03610b7057604051635b114e0560e01b815260040160405180910390fd5b6000818152600460205260408120805460ff19811660021790915560ff1690808080808080610b9e89611aa0565b985098505097509750975050965096506000604051806040016040528089815260200188815250905060016002811115610bda57610bda614e4b565b8560ff161480610bed575060028560ff16145b15610d14576000610c1d7fba0b74768b1de73590a53e1384870dcbc846e5c73bab23c07d71eaa7cbf8411b6115e5565b90508460ff16600114610c9e576040516333e3072160e01b81526001600160a01b038216906333e3072190610c56908590600401615027565b6020604051808303816000875af1158015610c75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c999190615057565b610d0d565b6040516349e5b64960e01b81526001600160a01b038216906349e5b64990610cca908590600401615027565b6020604051808303816000875af1158015610ce9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0d9190615057565b5050610de8565b60ff8516610dcf57606060001960ff881601610d59578460ff16600114610d4657610d418b8986866124a6565b610d52565b610d528b8986866125cd565b9050610dbe565b60ff8716610dbe5760018a6002811115610d7557610d75614e4b565b14610d93576040516386f8e37560e01b815260040160405180910390fd5b8460ff16600114610daf57610daa8b8986866128fe565b610dbb565b610dbb8b898686612b55565b90505b610dc98b84836130ab565b50610de8565b60405163641c695560e01b815260040160405180910390fd5b6040518a907fbce0bd6fef1367dca0b65255a7d010501f79e4dd96d4add4c3e42a419ae6457c90600090a250505050505050505050565b6000333014610e41576040516332b3785760e11b815260040160405180910390fd5b610e4c8484846131dc565b90505b9392505050565b6040516302e2825b60e51b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635c504b6090602401602060405180830381865afa158015610eba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ede9190615084565b610efa576040516270dbdf60e11b815260040160405180910390fd5b600081806020019051810190610f1091906150e4565b9050806020015151602003610f8b5760008160200151806020019051810190610f39919061515a565b6000818152600360205260408120805492935091610f5690615173565b9091555060405181907ffeea67837572d96738a25f3ac5fa382a1c601ead52e97fb27a02c6103360c06390600090a250505050565b6000808154610f9990615173565b90915550805160008054815260026020908152604090912091909155808201518051610fcb929082018101910161518c565b60008054815260056020908152604080832060019092528220909190610ff18482615296565b5050825161100491906020850190614831565b5050506000547f00000000000000000000000000000000000000000000000000000000000000006001600160401b0316846001600160401b03167f3371afb211a5a616ecaaab76f9466c9295fae2aa4e6dc1ed821b6eb25ee442cf60405160405180910390a45b505050565b60008181526006602090815260408083208054825181850281018501909352808352606094859490939183918301828280156110cb57602002820191906000526020600020905b8154815260200190600101908083116110b7575b505050505093508060020180548060200260200160405190810160405280929190818152602001828054801561112057602002820191906000526020600020905b81548152602001906001019080831161110c575b5050505050925080600501549150509193909250565b6000818152600560209081526040918290208054835181840281018401909452808452606093928301828280156111aa57602002820191906000526020600020906000905b825461010083900a900460ff1681526020600192830181810494850194909303909202910180841161117b5790505b50505050509050919050565b6111df7ff98729ec1ce0343ca1d11c51d1d2d3aa1a7b3f4f6876d0611e0a6fa86520a0cb611a71565b6111e88361146b565b600083815260066020526040902080541580611205575080548214155b15611223576040516344e945a960e01b815260040160405180910390fd5b6005810154156112455760405162aa3fd760e11b815260040160405180910390fd5b60008481526006602052604090206112619060020184846148d7565b50600084815260066020908152604080832042600590910155600290915281205460101c9060ff821660010361134757600086815260016020526040902080546112aa90614fd0565b80601f01602080910402602001604051908101604052809291908181526020018280546112d690614fd0565b80156113235780601f106112f857610100808354040283529160200191611323565b820191906000526020600020905b81548152906001019060200180831161130657829003601f168201915b505050505080602001905181019061133b9190615567565b610100015190506113f9565b6000868152600160205260409020805461136090614fd0565b80601f016020809104026020016040519081016040528092919081815260200182805461138c90614fd0565b80156113d95780601f106113ae576101008083540402835291602001916113d9565b820191906000526020600020905b8154815290600101906020018083116113bc57829003601f168201915b50505050508060200190518101906113f191906156f0565b610100015190505b6000868152600660205260409081902060040180546001600160a01b0319166001600160a01b0384161790555186907f78f133e107c1f55f0cb4abf0d9d0afc7d4949197a40bb9c88b97d51aec80f5cf9061145b9086908990899042906157b6565b60405180910390a2505050505050565b60005481111561148e576040516355da2ca360e11b815260040160405180910390fd5b50565b60006114bc7f6b50fa17b77d24e42e27a04b69fe50cd6967cfb767d18de0bd5fe7e1a32aa8686115e5565b604051632474521560e21b8152600481018590526001600160a01b03848116602483015291909116906391d1485490604401602060405180830381865afa15801561150b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061152f9190615084565b90505b92915050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636a42b8f86040518163ffffffff1660e01b8152600401602060405180830381865afa158015611599573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115bd919061515a565b9050806000036115e05760405163d0b3066f60e01b815260040160405180910390fd5b919050565b6040516321f8a72160e01b8152600481018290526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a721906024015b602060405180830381865afa15801561164e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611532919061583d565b60008280602001905181019061168891906150e4565b855190915060008190036116af576040516324cb170560e01b815260040160405180910390fd5b6116b885613241565b6116c360018361585a565b10156116e257604051635b6b08d760e01b815260040160405180910390fd5b6000838060200190518101906116f8919061586d565b905061171d8760008151811061171057611710614fba565b60200260200101516132d5565b6001600160a01b0316639783d0ef826000015160008151811061174257611742614fba565b60200260200101518a896040518060400160405280896000015181526020018d8a6020015160405160200161177892919061596f565b60408051601f198184030181529181529152516117989190602001615027565b60405160208183030381529060405286602001516000815181106117be576117be614fba565b60200260200101516040518663ffffffff1660e01b81526004016117e59493929190615994565b6000604051808303818588803b1580156117fe57600080fd5b505af1158015611812573d6000803e3d6000fd5b50505050506001821115611a0857611829856132e0565b602084015260015b828160ff161015611a06578760008151811061184f5761184f614fba565b602002602001015160ff16888260ff168151811061186f5761186f614fba565b602002602001015160ff16036118985760405163182d291160e11b815260040160405180910390fd5b6118a36001826159e4565b60ff16158015906118fc5750876118bb6001836159e4565b60ff16815181106118ce576118ce614fba565b602002602001015160ff16888260ff16815181106118ee576118ee614fba565b602002602001015160ff1611155b1561191a576040516322aa062d60e01b815260040160405180910390fd5b611932888260ff168151811061171057611710614fba565b6001600160a01b0316639783d0ef83600001518360ff168151811061195957611959614fba565b60200260200101518b8a886040516020016119749190615027565b60405160208183030381529060405287602001518760ff168151811061199c5761199c614fba565b60200260200101516040518663ffffffff1660e01b81526004016119c39493929190615994565b6000604051808303818588803b1580156119dc57600080fd5b505af11580156119f0573d6000803e3d6000fd5b5050505050806119ff906159fd565b9050611831565b505b5050505050505050565b6040516001600160a01b0383811660248301526044820183905261106b91859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050613312565b611a7b8133611491565b61148e576040516361381e6b60e11b8152600481018290526024015b60405180910390fd5b6000818152600260209081526040808320546001909252822080549192606092909182918291829182918291829190611ad890614fd0565b80601f0160208091040260200160405190810160405280929190818152602001828054611b0490614fd0565b8015611b515780601f10611b2657610100808354040283529160200191611b51565b820191906000526020600020905b815481529060010190602001808311611b3457829003601f168201915b50505050509750611b7560405180604001604052808b81526020018a815250613375565b96508895505050600884901c92505050601082901c601883901c602084901c60c085901c611ba281613241565b6000888152600360205260409020541015611bd057604051635b6b08d760e01b815260040160405180910390fd5b9193959799909294969850565b60ff80851690600886901c811690601087901c90861683148015611bff575081155b611c1c576040516330be21b360e11b815260040160405180910390fd5b6000856002811115611c3057611c30614e4b565b14611c4e576040516353b4315360e11b815260040160405180910390fd5b8360ff168160ff1614611c74576040516330be21b360e11b815260040160405180910390fd5b50505050505050565b6060611c87614912565b611c8f61496e565b8360ff16600103611cb55787806020019051810190611cae9190615567565b9150611cd7565b87806020019051810190611cc991906156f0565b9050611cd4816133a5565b91505b60a0820151518514611cfc5760405163707ea55960e11b815260040160405180910390fd5b611d298686848a7f000000000000000000000000000000000000000000000000000000000000000061359f565b91508360ff16600003611d87578160a00151600081518110611d4d57611d4d614fba565b6020908102919091018101515160a083015152604051611d6f91839101615b28565b60405160208183030381529060405292505050611dac565b81604051602001611d989190615bc8565b604051602081830303815290604052925050505b95945050505050565b6000611dd4604051806040016040528085815260200186815250613375565b9050848114611dfd57600085815260036020526040808220805484845291832091909155868252555b6000868152600160205260409020611e158582615296565b506000868152600460205260409020805483919060ff19166001836002811115611e4157611e41614e4b565b021790555060405186907f144d814d5dc6f17c1a88bc42c55d67392a51c818908ed7cca6118bc51a34b15390600090a2505050505050565b606060008087806020019051810190611e929190615567565b60408101515190915086908114611ebc57604051637753355f60e11b815260040160405180910390fd5b6000805b8281101561201d57898982818110611eda57611eda614fba565b90506020020135600003611f0157604051630f6fa54560e41b815260040160405180910390fd5b611fed611f2d7f494dfdc880823954ed6700117eb435b9bca3643417437b5781c1a89fba6e8b976115e5565b8560c001518381518110611f4357611f43614fba565b60200260200101518e848e8e87818110611f5f57611f5f614fba565b905060200201358d8d88818110611f7857611f78614fba565b9050602002016020810190611f8d919061500a565b8a602001518881518110611fa357611fa3614fba565b60200260200101518b604001518981518110611fc157611fc1614fba565b60200260200101518c608001518a81518110611fdf57611fdf614fba565b60200260200101518b613ae9565b90508560400151838151811061200557612005614fba565b60209081029190910101919091529150600101611ec0565b5080156123b1576000816001600160401b0381111561203e5761203e614a41565b604051908082528060200260200182016040528015612067578160200160208202803683370190505b5090506000826001600160401b0381111561208457612084614a41565b6040519080825280602002602001820160405280156120ad578160200160208202803683370190505b5090506000836001600160401b038111156120ca576120ca614a41565b6040519080825280602002602001820160405280156120f3578160200160208202803683370190505b5090506000846001600160401b0381111561211057612110614a41565b604051908082528060200260200182016040528015612139578160200160208202803683370190505b5090506000856001600160401b0381111561215657612156614a41565b60405190808252806020026020018201604052801561217f578160200160208202803683370190505b5090506000866001600160401b0381111561219c5761219c614a41565b6040519080825280602002602001820160405280156121c5578160200160208202803683370190505b5090506000805b8981101561237f578a6040015181815181106121ea576121ea614fba565b6020026020010151600014612377578a60200151818151811061220f5761220f614fba565b602002602001015188838151811061222957612229614fba565b6020026020010181815250508a60400151818151811061224b5761224b614fba565b602002602001015187838151811061226557612265614fba565b6020026020010181815250508a60600151818151811061228757612287614fba565b60200260200101518683815181106122a1576122a1614fba565b6020026020010181815250508a6080015181815181106122c3576122c3614fba565b60200260200101518583815181106122dd576122dd614fba565b6020026020010181815250508a60c0015181815181106122ff576122ff614fba565b602002602001015184838151811061231957612319614fba565b6020026020010190151590811515815250508a60e00151818151811061234157612341614fba565b602002602001015183838151811061235b5761235b614fba565b9115156020928302919091019091015261237482615173565b91505b6001016121cc565b5050602089019590955260408801939093526060870191909152608086015260c085015260e0840152600193506123b6565b600293505b826040516020016123c79190615bc8565b6040516020818303038152906040529450505050965096945050505050565b6060600080858060200190518101906123ff91906156f0565b90508460000361242257604051630f6fa54560e41b815260040160405180910390fd5b61246e61244e7f494dfdc880823954ed6700117eb435b9bca3643417437b5781c1a89fba6e8b976115e5565b8260c0015189600089898760200151886040015189608001516000613ae9565b50604080840192909252905190925061248b908290602001615b28565b60405160208183030381529060405292505094509492505050565b60606000848060200190518101906124be91906156f0565b6040805160208082018a905260008284015282518083038401815260609092019092526101208301528101519091506124f690613e80565b6125135760405163a412f06560e01b815260040160405180910390fd5b6125208160200151613f19565b6001600160a01b031663ef164fef8286866040518463ffffffff1660e01b815260040161254f93929190615cdb565b6020604051808303816000875af192505050801561258a575060408051601f3d908101601f191682019092526125879181019061515a565b60015b6125b2576125aa8482600001516001600285602001518660400151613f2d565b9150506125c5565b5050506040805160208101909152600081525b949350505050565b60606000848060200190518101906125e59190615567565b6020810151519091506000908161261b7fbcc180fb907e9ae431665de4bc74305c00b7b27442aadd477980ecc4bb14c0116115e5565b905060005b828110156128b457816001600160a01b031663b5c756978660200151838151811061264d5761264d614fba565b60200260200101516040518263ffffffff1660e01b815260040161267391815260200190565b602060405180830381865afa158015612690573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b49190615084565b6126d15760405163a412f06560e01b815260040160405180910390fd5b6126f7856020015182815181106126ea576126ea614fba565b6020026020010151613f19565b6001600160a01b031663ef164fef604051806101400160405280886000015181526020018860200151858151811061273157612731614fba565b602002602001015181526020018860400151858151811061275457612754614fba565b602002602001015181526020018860600151858151811061277757612777614fba565b602002602001015181526020018860800151858151811061279a5761279a614fba565b602002602001015181526020018860a0015185815181106127bd576127bd614fba565b602002602001015181526020016000151581526020016000151581526020018861010001516001600160a01b031681526020018d8560405160200161280c929190918252602082015260400190565b6040516020818303038152906040528152508a8a6040518463ffffffff1660e01b815260040161283e93929190615cdb565b6020604051808303816000875af1925050508015612879575060408051601f3d908101601f191682019092526128769181019061515a565b60015b61288657600193506128ac565b5060008560400151828151811061289f5761289f614fba565b6020026020010181815250505b600101612620565b5082156128e2576128d7878560000151600160028860200151896040015161405d565b9450505050506125c5565b5050604080516020810190915260008152979650505050505050565b606060008480602001905181019061291691906156f0565b905060006129278260200151613f19565b90506000612934826140cc565b60408481015190516370a0823160e01b815230600482015291925082916001600160a01b038316906370a0823190602401602060405180830381865afa158015612982573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129a6919061515a565b10612b3c5760408401516129c6906001600160a01b03831690859061410c565b604051634af278ed60e11b81526001600160a01b038416906395e4f1da906129f69087908b908b90600401615cdb565b6020604051808303816000875af1925050508015612a31575060408051601f3d908101601f19168201909252612a2e9181019061515a565b60015b612afc576040840151612a50906001600160a01b03831690859061419c565b60008981526006602090815260408083208783015181546001808201845583875285872090910191909155808201805480830182559086528486200180546001600160a01b0319166001600160a01b03891617905560039091018054918201815584528284209281049092018054601f9093166101000a60ff0219909216909155518a917f21c4f33a94342256a428d6cb08476047bdb16e6866308b7d904df8990eb781c891a26128e2565b8015801590612b0d57508460e00151155b15612b3657612b2a88866000015160006001896020015186613f2d565b955050505050506125c5565b506128e2565b604051630399226960e41b815260040160405180910390fd5b6060600084806020019051810190612b6d9190615567565b90506000612b7e8260200151614259565b6020830151519091506000908180805b8381101561302b5786604001518181518110612bac57612bac614fba565b602002602001015160001461302357612bdd868281518110612bd057612bd0614fba565b60200260200101516140cc565b945086604001518181518110612bf557612bf5614fba565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa158015612c44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c68919061515a565b10612b3c57612cc1868281518110612c8257612c82614fba565b602002602001015188604001518381518110612ca057612ca0614fba565b6020026020010151876001600160a01b031661410c9092919063ffffffff16565b612cc96149c9565b868281518110612cdb57612cdb614fba565b60200260200101516001600160a01b03166395e4f1da6040518061014001604052808b6000015181526020018b602001518681518110612d1d57612d1d614fba565b602002602001015181526020018b604001518681518110612d4057612d40614fba565b602002602001015181526020018b606001518681518110612d6357612d63614fba565b602002602001015181526020018b608001518681518110612d8657612d86614fba565b602002602001015181526020018481526020016000151581526020018b60e001518681518110612db857612db8614fba565b6020026020010151151581526020018b61010001516001600160a01b031681526020018b61012001518152508d8d6040518463ffffffff1660e01b8152600401612e0493929190615cdb565b6020604051808303816000875af1925050508015612e3f575060408051601f3d908101601f19168201909252612e3c9181019061515a565b60015b612f9f57612e97878381518110612e5857612e58614fba565b602002602001015189604001518481518110612e7657612e76614fba565b6020026020010151886001600160a01b031661419c9092919063ffffffff16565b60008d81526006602090815260409091209089015180516001955084908110612ec257612ec2614fba565b60209081029190910181015182546001810184556000938452918320909101556040890151805184908110612ef957612ef9614fba565b602002602001018181525050600660008e8152602001908152602001600020600101612f30888481518110612bd057612bd0614fba565b8154600180820184556000938452602080852090920180546001600160a01b0319166001600160a01b0394909416939093179092558f83526006815260408320600301805492830181558352918290209181049091018054601f9092166101000a60ff02199091169055613021565b8015801590612fc957508860e001518381518110612fbf57612fbf614fba565b6020026020010151155b15612ffa57600194508089604001518481518110612fe957612fe9614fba565b60200260200101818152505061301f565b60008960400151848151811061301257613012614fba565b6020026020010181815250505b505b505b600101612b8e565b50801561305e576040518b907f21c4f33a94342256a428d6cb08476047bdb16e6866308b7d904df8990eb781c890600090a25b811561308d57613080898760000151600060018a602001518b6040015161405d565b96505050505050506125c5565b50506040805160208101909152600081529998505050505050505050565b80511561106b5760008381526005602090815260408083208054825181850281018501909352808352919290919083018282801561312657602002820191906000526020600020906000905b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116130f75790505b5050505050905060006131587fab437a16135e856111e538dc45051dd9c2778c6069d25a22fb9ac4766c356aa16115e5565b6001600160a01b0316633283166a8584866040518463ffffffff1660e01b815260040161318793929190615d17565b600060405180830381865afa1580156131a4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526131cc9190810190615d4b565b9150506105653383868685611672565b6000828411156131ff5760405163c8a403d160e01b815260040160405180910390fd5b600061271061320e848261585a565b6132189086615d87565b6132229190615d9e565b905080851015613236576000915050610e4f565b506001949350505050565b604051631049a0db60e01b81526001600160401b03821660048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631049a0db90602401602060405180830381865afa1580156132b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611532919061515a565b60006115328261430b565b606081805190602001206040516020016132fc91815260200190565b6040516020818303038152906040529050919050565b60006133276001600160a01b0384168361435d565b9050805160001415801561334c57508080602001905181019061334a9190615084565b155b1561106b57604051635274afe760e01b81526001600160a01b0384166004820152602401611a97565b6000816040516020016133889190615027565b604051602081830303815290604052805190602001209050919050565b6133ad614912565b604080516001808252818301909252600091602080830190803683370190505090508260200151816000815181106133e7576133e7614fba565b602090810291909101015260408051600180825281830190925260009181602001602082028036833701905050905083604001518160008151811061342e5761342e614fba565b602090810291909101015260408051600180825281830190925260009181602001602082028036833701905050905084606001518160008151811061347557613475614fba565b60209081029190910101526040805160018082528183019092526000918160200160208202803683370190505090508560800151816000815181106134bc576134bc614fba565b6020908102919091010152604080516001808252818301909252600091816020015b6134e66149c9565b8152602001906001900390816134de5790505090508660a001518160008151811061351357613513614fba565b60200260200101819052506040518061014001604052808860000151815260200186815260200185815260200184815260200183815260200182815260200161355f8960c0015161436b565b81526020016135718960e0015161436b565b81526020018861010001516001600160a01b0316815260200188610120015181525095505050505050919050565b6135a7614912565b60a0840151516000805b82811015613adc578888828181106135cb576135cb614fba565b90506020028101906135dd9190615dc0565b158015915061360e57508660a0015181815181106135fd576135fd614fba565b602002602001015160000151516000145b15613ad45761362c876020015182815181106126ea576126ea614fba565b9150613637306143b6565b60ff16826001600160a01b03166391deb8826040518163ffffffff1660e01b8152600401602060405180830381865afa158015613678573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061369c9190615e06565b60ff1603613ad4576136ca8760a0015182815181106136bd576136bd614fba565b6020026020010151614445565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e85b2b548960a00151848151811061371157613711614fba565b6020026020010151606001516040518263ffffffff1660e01b8152600401613742919060ff91909116815260200190565b602060405180830381865afa15801561375f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613783919061583d565b9050806001600160a01b031663c87439eb6040518061012001604052808d8d878181106137b2576137b2614fba565b90506020028101906137c49190615dc0565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506001600160401b03808b1660208301528b16604082015260a08c015180516060909201918790811061382f5761382f614fba565b6020026020010151608001516001600160401b03168152602001600015158152602001866001600160a01b031681526020018b61010001516001600160a01b0316815260200161387e876140cc565b6001600160a01b0316815260006020909101526040516001600160e01b031960e084901b1681526138b29190600401615e23565b602060405180830381865afa1580156138cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f39190615084565b50613a3a816001600160a01b0316639bbbb5c88c8c8681811061391857613918614fba565b905060200281019061392a9190615dc0565b60006040518463ffffffff1660e01b815260040161394a93929190615ef6565b602060405180830381865afa158015613967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061398b919061515a565b846001600160a01b031663b7ba28cd8b6040015186815181106139b0576139b0614fba565b60200260200101516040518263ffffffff1660e01b81526004016139d691815260200190565b602060405180830381865afa1580156139f3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a17919061515a565b8a608001518581518110613a2d57613a2d614fba565b60200260200101516131dc565b613a57576040516358d0562960e11b815260040160405180910390fd5b898983818110613a6957613a69614fba565b9050602002810190613a7b9190615dc0565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050505060a0890151805184908110613ac657613ac6614fba565b602090810291909101015152505b6001016135b1565b5094979650505050505050565b600080806001600160a01b038816613b14576040516331b5a77960e11b815260040160405180910390fd5b60008c15613cf757898e6001600160a01b031663c830c85a8e8e6040518363ffffffff1660e01b8152600401613b54929190918252602082015260400190565b602060405180830381865afa158015613b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b95919061515a565b14613cf7576000808f6001600160a01b03166395c2c5d78f8f6040518363ffffffff1660e01b8152600401613bd4929190918252602082015260400190565b6040805180830381865afa158015613bf0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c149190615f2e565b915091508b8114613c38576040516320590e3d60e11b815260040160405180910390fd5b8a6001600160a01b0316826001600160a01b031614613c6a576040516325bfc2e360e11b815260040160405180910390fd5b5060008d815260066020908152604082208054600181810183558285528385209091018d9055818101805480830182559085528385200180546001600160a01b039096166001600160a01b03199096169590951790945560030180548085018255908352818320918104909101805460ff601f9093166101000a9283021916909117905597506002935090505b80613e6b5760405163803c15df60e01b8152600481018b90526024810188905260448101879052309063803c15df90606401602060405180830381865afa925050508015613d62575060408051601f3d908101601f19168201909252613d5f91810190615084565b60015b613d6f5760019250613d7f565b8015613d7d578a9750600193505b505b613d8888613e80565b8015613da557506001836002811115613da357613da3614e4b565b145b613e525760008c815260066020908152604082208054600181810183559184529183209091018a9055613ddb908a908c9061447e565b60008e815260066020908152604082206001808201805480830182559085528385200180546001600160a01b0319166001600160a01b039690961695909517909455600301805493840181558252808220908304018054601f9093166101000a60ff0219909216909155975060029350613e6b9050565b613e5e888a600061447e565b50613e6885615173565b94505b50949c909b5091995090975050505050505050565b6000613eab7fbcc180fb907e9ae431665de4bc74305c00b7b27442aadd477980ecc4bb14c0116115e5565b6001600160a01b031663b5c75697836040518263ffffffff1660e01b8152600401613ed891815260200190565b602060405180830381865afa158015613ef5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115329190615084565b6000613f2482614565565b50909392505050565b60606040518060400160405280613fe6876001811115613f4f57613f4f614e4b565b876002811115613f6157613f61614e4b565b6000613f6c306143b6565b8d7f000000000000000000000000000000000000000000000000000000000000000060ff9590951660089490941b61ff00169390931760109290921b62ff0000169190911760189190911b63ff000000161760209190911b640100000000600160c01b03161760c09190911b6001600160c01b0319161790565b815260408051606080820183528a8252602082810189815292840188815284518083018e90529351948401949094529251908201529101906080015b60408051601f198184030181529181529152516140429190602001615027565b60405160208183030381529060405290509695505050505050565b6060604051806040016040528061409c87600181111561407f5761407f614e4b565b87600281111561409157614091614e4b565b6001613f6c306143b6565b81526020016040518060600160405280898152602001868152602001858152506040516020016140229190615f5c565b6000816001600160a01b031663b60262ca6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561164e573d6000803e3d6000fd5b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa15801561415c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614180919061515a565b905061419684846141918585614fa7565b614599565b50505050565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa1580156141ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614210919061515a565b90508181101561424c5760405163e570110f60e01b81526001600160a01b03841660048201526024810182905260448101839052606401611a97565b6141968484848403614599565b8051606090806001600160401b0381111561427657614276614a41565b60405190808252806020026020018201604052801561429f578160200160208202803683370190505b50915060005b81811015614304576142cf8482815181106142c2576142c2614fba565b6020026020010151614565565b9050508382815181106142e4576142e4614fba565b6001600160a01b03909216602092830291909101909101526001016142a5565b5050919050565b604051630eff125d60e01b815260ff821660048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630eff125d90602401611631565b606061152f83836000614629565b6040805160018082528183019092526060916020808301908036833701905050905081816000815181106143a1576143a1614fba565b91151560209283029190910190910152919050565b604051632f6438ab60e01b81526001600160a01b0382811660048301526000917f000000000000000000000000000000000000000000000000000000000000000090911690632f6438ab90602401602060405180830381865afa158015614421573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115329190615e06565b60208101516001600160a01b03161580614460575080515115155b1561148e57604051630c57767d60e41b815260040160405180910390fd5b600061448984613f19565b6001600160a01b031663b60262ca6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156144e2575060408051601f3d908101601f191682019092526144df9181019061583d565b60015b15614527578280156145065750836001600160a01b0316816001600160a01b031614155b15614524576040516325bfc2e360e11b815260040160405180910390fd5b90505b811580156145475750826001600160a01b0316816001600160a01b031614155b15610e4f576040516325bfc2e360e11b815260040160405180910390fd5b8060a081901c60c082901c60008190036145925760405163030042b760e01b815260040160405180910390fd5b9193909250565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b1790526145ea84826146c6565b614196576040516001600160a01b0384811660248301526000604483015261461f91869182169063095ea7b390606401611a3f565b6141968482613312565b60608147101561464e5760405163cd78605960e01b8152306004820152602401611a97565b600080856001600160a01b0316848660405161466a9190615f9f565b60006040518083038185875af1925050503d80600081146146a7576040519150601f19603f3d011682016040523d82523d6000602084013e6146ac565b606091505b50915091506146bc868383614769565b9695505050505050565b6000806000846001600160a01b0316846040516146e39190615f9f565b6000604051808303816000865af19150503d8060008114614720576040519150601f19603f3d011682016040523d82523d6000602084013e614725565b606091505b509150915081801561474f57508051158061474f57508080602001905181019061474f9190615084565b8015611dac5750505050506001600160a01b03163b151590565b60608261477e57614779826147c5565b610e4f565b815115801561479557506001600160a01b0384163b155b156147be57604051639996b31560e01b81526001600160a01b0385166004820152602401611a97565b5080610e4f565b8051156147d55780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b508054600082559060005260206000209081019061148e91906149fe565b50805460008255601f01602090049060005260206000209081019061148e91906149fe565b82805482825590600052602060002090601f016020900481019282156148c75791602002820160005b8382111561489857835183826101000a81548160ff021916908360ff160217905550926020019260010160208160000104928301926001030261485a565b80156148c55782816101000a81549060ff0219169055600101602081600001049283019260010302614898565b505b506148d39291506149fe565b5090565b8280548282559060005260206000209081019282156148c7579160200282015b828111156148c75782358255916020019190600101906148f7565b604051806101400160405280600081526020016060815260200160608152602001606081526020016060815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001606081525090565b60405180610140016040528060008152602001600081526020016000815260200160008152602001600081526020016149a56149c9565b81526000602082018190526040820181905260608083019190915260809091015290565b6040805160c081018252606080825260006020830181905292820183905281018290526080810182905260a081019190915290565b5b808211156148d357600081556001016149ff565b600060208284031215614a2557600080fd5b5035919050565b6001600160a01b038116811461148e57600080fd5b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715614a7957614a79614a41565b60405290565b60405161014081016001600160401b0381118282101715614a7957614a79614a41565b604051601f8201601f191681016001600160401b0381118282101715614aca57614aca614a41565b604052919050565b60006001600160401b03821115614aeb57614aeb614a41565b5060051b60200190565b60ff8116811461148e57600080fd5b6001600160401b038116811461148e57600080fd5b80356115e081614b04565b60006001600160401b03821115614b3d57614b3d614a41565b50601f01601f191660200190565b600082601f830112614b5c57600080fd5b8135614b6f614b6a82614b24565b614aa2565b818152846020838601011115614b8457600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a08688031215614bb957600080fd5b8535614bc481614a2c565b94506020868101356001600160401b0380821115614be157600080fd5b818901915089601f830112614bf557600080fd5b8135614c03614b6a82614ad2565b81815260059190911b8301840190848101908c831115614c2257600080fd5b938501935b82851015614c49578435614c3a81614af5565b82529385019390850190614c27565b9850614c5a91505060408a01614b19565b95506060890135925080831115614c7057600080fd5b614c7c8a848b01614b4b565b94506080890135925080831115614c9257600080fd5b5050614ca088828901614b4b565b9150509295509295909350565b60005b83811015614cc8578181015183820152602001614cb0565b50506000910152565b60008151808452614ce9816020860160208601614cad565b601f01601f19169290920160200192915050565b60208152600061152f6020830184614cd1565b60008083601f840112614d2257600080fd5b5081356001600160401b03811115614d3957600080fd5b6020830191508360208260051b8501011115614d5457600080fd5b9250929050565b600080600060408486031215614d7057600080fd5b8335925060208401356001600160401b03811115614d8d57600080fd5b614d9986828701614d10565b9497909650939450505050565b600080600080600060608688031215614dbe57600080fd5b8535945060208601356001600160401b0380821115614ddc57600080fd5b614de889838a01614d10565b90965094506040880135915080821115614e0157600080fd5b50614e0e88828901614d10565b969995985093965092949392505050565b600080600060608486031215614e3457600080fd5b505081359360208301359350604090920135919050565b634e487b7160e01b600052602160045260246000fd5b6020810160038310614e8357634e487b7160e01b600052602160045260246000fd5b91905290565b60008060408385031215614e9c57600080fd5b8235614ea781614b04565b915060208301356001600160401b03811115614ec257600080fd5b614ece85828601614b4b565b9150509250929050565b60008151808452602080850194506020840160005b83811015614f0957815187529582019590820190600101614eed565b509495945050505050565b606081526000614f276060830186614ed8565b8281036020840152614f398186614ed8565b915050826040830152949350505050565b60008151808452602080850194506020840160005b83811015614f0957815160ff1687529582019590820190600101614f5f565b60208152600061152f6020830184614f4a565b634e487b7160e01b600052601160045260246000fd5b8082018082111561153257611532614f91565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680614fe457607f821691505b60208210810361500457634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561501c57600080fd5b8135610e4f81614a2c565b6020815281516020820152600060208301516040808401526125c56060840182614cd1565b80516115e081614b04565b60006020828403121561506957600080fd5b8151610e4f81614b04565b805180151581146115e057600080fd5b60006020828403121561509657600080fd5b61152f82615074565b600082601f8301126150b057600080fd5b81516150be614b6a82614b24565b8181528460208386010111156150d357600080fd5b6125c5826020830160208701614cad565b6000602082840312156150f657600080fd5b81516001600160401b038082111561510d57600080fd5b908301906040828603121561512157600080fd5b615129614a57565b8251815260208301518281111561513f57600080fd5b61514b8782860161509f565b60208301525095945050505050565b60006020828403121561516c57600080fd5b5051919050565b60006001820161518557615185614f91565b5060010190565b6000806040838503121561519f57600080fd5b82516001600160401b03808211156151b657600080fd5b818501915085601f8301126151ca57600080fd5b815160206151da614b6a83614ad2565b82815260059290921b840181019181810190898411156151f957600080fd5b948201945b8386101561522057855161521181614af5565b825294820194908201906151fe565b9188015191965090935050508082111561523957600080fd5b50614ece8582860161509f565b601f82111561106b576000816000526020600020601f850160051c8101602086101561526f5750805b601f850160051c820191505b8181101561528e5782815560010161527b565b505050505050565b81516001600160401b038111156152af576152af614a41565b6152c3816152bd8454614fd0565b84615246565b602080601f8311600181146152f857600084156152e05750858301515b600019600386901b1c1916600185901b17855561528e565b600085815260208120601f198616915b8281101561532757888601518255948401946001909101908401615308565b50858210156153455787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600082601f83011261536657600080fd5b81516020615376614b6a83614ad2565b8083825260208201915060208460051b87010193508684111561539857600080fd5b602086015b848110156153b4578051835291830191830161539d565b509695505050505050565b80516115e081614a2c565b600060c082840312156153dc57600080fd5b60405160c081016001600160401b0382821081831117156153ff576153ff614a41565b81604052829350845191508082111561541757600080fd5b506154248582860161509f565b825250602083015161543581614a2c565b6020820152604083015161544881614a2c565b6040820152606083015161545b81614af5565b606082015261546c6080840161504c565b608082015260a083015160a08201525092915050565b600082601f83011261549357600080fd5b815160206154a3614b6a83614ad2565b82815260059290921b840181019181810190868411156154c257600080fd5b8286015b848110156153b45780516001600160401b038111156154e55760008081fd5b6154f38986838b01016153ca565b8452509183019183016154c6565b600082601f83011261551257600080fd5b81516020615522614b6a83614ad2565b8083825260208201915060208460051b87010193508684111561554457600080fd5b602086015b848110156153b45761555a81615074565b8352918301918301615549565b60006020828403121561557957600080fd5b81516001600160401b038082111561559057600080fd5b9083019061014082860312156155a557600080fd5b6155ad614a7f565b825181526020830151828111156155c357600080fd5b6155cf87828601615355565b6020830152506040830151828111156155e757600080fd5b6155f387828601615355565b60408301525060608301518281111561560b57600080fd5b61561787828601615355565b60608301525060808301518281111561562f57600080fd5b61563b87828601615355565b60808301525060a08301518281111561565357600080fd5b61565f87828601615482565b60a08301525060c08301518281111561567757600080fd5b61568387828601615501565b60c08301525060e08301518281111561569b57600080fd5b6156a787828601615501565b60e0830152506101006156bb8185016153bf565b9082015261012083810151838111156156d357600080fd5b6156df8882870161509f565b918301919091525095945050505050565b60006020828403121561570257600080fd5b81516001600160401b038082111561571957600080fd5b90830190610140828603121561572e57600080fd5b615736614a7f565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a08301518281111561577457600080fd5b615780878286016153ca565b60a08301525061579260c08401615074565b60c08201526157a360e08401615074565b60e08201526101006156bb8185016153bf565b600060608201606083528087548083526080850191508860005260209250602060002060005b828110156157f8578154845292840192600191820191016157dc565b50505083810360208501528581526001600160fb1b0386111561581a57600080fd5b8560051b9150818760208301376040939093019390935250016020019392505050565b60006020828403121561584f57600080fd5b8151610e4f81614a2c565b8181038181111561153257611532614f91565b6000602080838503121561588057600080fd5b82516001600160401b038082111561589757600080fd5b90840190604082870312156158ab57600080fd5b6158b3614a57565b8251828111156158c257600080fd5b6158ce88828601615355565b82525083830151828111156158e257600080fd5b80840193505086601f8401126158f757600080fd5b8251615905614b6a82614ad2565b81815260059190911b8401850190858101908983111561592457600080fd5b8686015b8381101561595c578051868111156159405760008081fd5b61594e8c8a838b010161509f565b845250918701918701615928565b5095830195909552509695505050505050565b6040815260006159826040830185614f4a565b8281036020840152611dac8185614cd1565b6001600160a01b03851681526001600160401b03841660208201526080604082018190526000906159c790830185614cd1565b82810360608401526159d98185614cd1565b979650505050505050565b60ff828116828216039081111561153257611532614f91565b600060ff821660ff8103615a1357615a13614f91565b60010192915050565b6000815160c08452615a3160c0850182614cd1565b9050602083015160018060a01b038082166020870152806040860151166040870152505060ff60608401511660608501526001600160401b03608084015116608085015260a083015160a08501528091505092915050565b6000610140825184526020830151602085015260408301516040850152606083015160608501526080830151608085015260a08301518160a0860152615ad182860182615a1c565b91505060c0830151615ae760c086018215159052565b5060e0830151615afb60e086018215159052565b50610100838101516001600160a01b03169085015261012080840151858303828701526146bc8382614cd1565b60208152600061152f6020830184615a89565b60008282518085526020808601955060208260051b8401016020860160005b84811015615b8857601f19868403018952615b76838351615a1c565b98840198925090830190600101615b5a565b5090979650505050505050565b60008151808452602080850194506020840160005b83811015614f09578151151587529582019590820190600101615baa565b602081528151602082015260006020830151610140806040850152615bf1610160850183614ed8565b91506040850151601f1980868503016060870152615c0f8483614ed8565b93506060870151915080868503016080870152615c2c8483614ed8565b935060808701519150808685030160a0870152615c498483614ed8565b935060a08701519150808685030160c0870152615c668483615b3b565b935060c08701519150808685030160e0870152615c838483615b95565b935060e08701519150610100818786030181880152615ca28584615b95565b945080880151925050610120615cc2818801846001600160a01b03169052565b8701518685039091018387015290506146bc8382614cd1565b606081526000615cee6060830186615a89565b6001600160a01b03949094166020830152506001600160401b0391909116604090910152919050565b6001600160401b0384168152606060208201526000615d396060830185614f4a565b82810360408401526146bc8185614cd1565b60008060408385031215615d5e57600080fd5b8251915060208301516001600160401b03811115615d7b57600080fd5b614ece8582860161509f565b808202811582820484141761153257611532614f91565b600082615dbb57634e487b7160e01b600052601260045260246000fd5b500490565b6000808335601e19843603018112615dd757600080fd5b8301803591506001600160401b03821115615df157600080fd5b602001915036819003821315614d5457600080fd5b600060208284031215615e1857600080fd5b8151610e4f81614af5565b6020815260008251610120806020850152615e42610140850183614cd1565b91506020850151615e5e60408601826001600160401b03169052565b5060408501516001600160401b03811660608601525060608501516001600160401b038116608086015250608085015180151560a08601525060a08501516001600160a01b03811660c08601525060c08501516001600160a01b03811660e08601525060e0850151610100615edd818701836001600160a01b03169052565b909501516001600160a01b031693019290925250919050565b6040815282604082015282846060830137600060608483018101919091529115156020820152601f909201601f191690910101919050565b60008060408385031215615f4157600080fd5b8251615f4c81614a2c565b6020939093015192949293505050565b60208152815160208201526000602083015160606040840152615f826080840182614ed8565b90506040840151601f19848303016060850152611dac8282614ed8565b60008251615fb1818460208701614cad565b919091019291505056fea2646970667358221220374638a3255ecd4b127cbbc75e1971d2594ffd45b6f30f95ddae7ab6ec7214fd64736f6c6343000817003300000000000000000000000017a332dc7b40ae701485023b219e9d6f493a2514
Deployed Bytecode
0x6080604052600436106101095760003560e01c80635aef948011610095578063cc2d8abd11610064578063cc2d8abd1461033e578063d468711a1461035e578063d49616061461038d578063d830364e146103ba578063e17d89e8146103e757600080fd5b80635aef948014610272578063803c15df1461028557806385e1f4d0146102b5578063b63d36a51461030157600080fd5b80632d46647d116100dc5780632d46647d146101b8578063361ad42b146101d857806336445ffd14610205578063439890e214610232578063474fd8741461025257600080fd5b806313bff0121461010e57806313c02a591461013057806323de31e11461015957806324c73dda1461016c575b600080fd5b34801561011a57600080fd5b5061012e610129366004614a13565b610407565b005b34801561013c57600080fd5b5061014660005481565b6040519081526020015b60405180910390f35b61012e610167366004614ba1565b6104fe565b34801561017857600080fd5b506101a07f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a251481565b6040516001600160a01b039091168152602001610150565b3480156101c457600080fd5b5061012e6101d3366004614a13565b61056c565b3480156101e457600080fd5b506101f86101f3366004614a13565b610815565b6040516101509190614cfd565b34801561021157600080fd5b50610146610220366004614a13565b60026020526000908152604090205481565b34801561023e57600080fd5b5061012e61024d366004614d5b565b6108af565b34801561025e57600080fd5b5061012e61026d366004614da6565b610980565b61012e610280366004614a13565b610afb565b34801561029157600080fd5b506102a56102a0366004614e1f565b610e1f565b6040519015158152602001610150565b3480156102c157600080fd5b506102e97f000000000000000000000000000000000000000000000000000000000000000181565b6040516001600160401b039091168152602001610150565b34801561030d57600080fd5b5061033161031c366004614a13565b60046020526000908152604090205460ff1681565b6040516101509190614e61565b34801561034a57600080fd5b5061012e610359366004614e89565b610e56565b34801561036a57600080fd5b5061037e610379366004614a13565b611070565b60405161015093929190614f14565b34801561039957600080fd5b506101466103a8366004614a13565b60036020526000908152604090205481565b3480156103c657600080fd5b506103da6103d5366004614a13565b611136565b6040516101509190614f7e565b3480156103f357600080fd5b5061012e610402366004614d5b565b6111b6565b6104108161146b565b600081815260066020526040902060048101546001600160a01b031633148061045e575061045e7f3c98683c4fc1f07b3a173ce23e8e5b9ee147da7d8df6f5e0da4c07c15e354a0733611491565b61047b57604051630363e30760e61b815260040160405180910390fd5b600581015415806104a1575061048f611538565b816005015461049e9190614fa7565b42115b156104bf576040516360387b3360e01b815260040160405180910390fd5b6000828152600660205260408082206005018290555183917f7e98ef42b90939b396b85416fa66b14f7a5c284f7a7e794d995b3fad3c6e85cb91a25050565b6105277f3a2f5529773e03d975be44bdae98a8509bdf1159e407504e558536cde56cf6ac6115e5565b6001600160a01b0316336001600160a01b0316146105585760405163158a2f6b60e01b815260040160405180910390fd5b6105658585858585611672565b5050505050565b6105758161146b565b6000818152600660205260409020600581015415806105aa5750610597611538565b81600501546105a69190614fa7565b4211155b156105c857604051633527c42560e01b815260040160405180910390fd5b6000600582018190556002820154905b81811015610787578260030181815481106105f5576105f5614fba565b90600052602060002090602091828204019190069054906101000a900460ff1615610719576106437f494dfdc880823954ed6700117eb435b9bca3643417437b5781c1a89fba6e8b976115e5565b60048401546001850180546001600160a01b03938416936310d7d359931691908590811061067357610673614fba565b6000918252602090912001546002870180546001600160a01b0390921691869081106106a1576106a1614fba565b6000918252602090912001546040516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b1580156106fc57600080fd5b505af1158015610710573d6000803e3d6000fd5b5050505061077f565b600483015460028401805461077f926001600160a01b031691908490811061074357610743614fba565b906000526020600020015485600101848154811061076357610763614fba565b6000918252602090912001546001600160a01b03169190611a12565b6001016105d8565b506000838152600660205260408120906107a182826147ee565b6107af6001830160006147ee565b6107bd6002830160006147ee565b6107cb60038301600061480c565b506004810180546001600160a01b03191690556000600590910181905560405184917f4dcd0d064503785f7194bc0d094f808cd1df65b1440424e51cd211c9672f77cc91a2505050565b6001602052600090815260409020805461082e90614fd0565b80601f016020809104026020016040519081016040528092919081815260200182805461085a90614fd0565b80156108a75780601f1061087c576101008083540402835291602001916108a7565b820191906000526020600020905b81548152906001019060200180831161088a57829003601f168201915b505050505081565b6108d87f67ae681a1ce853cc4fa2ec7bd45049225042d6a828b9865aca9ef1218a52bcfc611a71565b6108e18361146b565b60008060008060006108f288611aa0565b985050509650505094509450945061092e8560018081111561091657610916614e4b565b60008b81526004602052604090205460ff1685611bdd565b61093b8482898986611c7d565b935061094b888486886001611db5565b60405188907f144d814d5dc6f17c1a88bc42c55d67392a51c818908ed7cca6118bc51a34b15390600090a25050505050505050565b6109a97f67ae681a1ce853cc4fa2ec7bd45049225042d6a828b9865aca9ef1218a52bcfc611a71565b6109b28561146b565b6000806000806109c189611aa0565b505050955050509350935093506109fd84600060018111156109e5576109e5614e4b565b60008c81526004602052604090205460ff1684611bdd565b600060ff821615610a2057610a168a8589898d8d611e79565b9094509050610a72565b610a6c8a8589896000818110610a3857610a38614fba565b905060200201358c8c6000818110610a5257610a52614fba565b9050602002016020810190610a67919061500a565b6123e6565b90945090505b610a7f8a84868885611db5565b6002816002811115610a9357610a93614e4b565b03610aef576040518a907fbce0bd6fef1367dca0b65255a7d010501f79e4dd96d4add4c3e42a419ae6457c90600090a26040518a907f21c4f33a94342256a428d6cb08476047bdb16e6866308b7d904df8990eb781c890600090a25b50505050505050505050565b610b247ff7c2c1de3464c8fee0ad8a71a80d665aeafd6a725243593923472fe5e76e45b1611a71565b610b2d8161146b565b600260008281526004602052604090205460ff166002811115610b5257610b52614e4b565b03610b7057604051635b114e0560e01b815260040160405180910390fd5b6000818152600460205260408120805460ff19811660021790915560ff1690808080808080610b9e89611aa0565b985098505097509750975050965096506000604051806040016040528089815260200188815250905060016002811115610bda57610bda614e4b565b8560ff161480610bed575060028560ff16145b15610d14576000610c1d7fba0b74768b1de73590a53e1384870dcbc846e5c73bab23c07d71eaa7cbf8411b6115e5565b90508460ff16600114610c9e576040516333e3072160e01b81526001600160a01b038216906333e3072190610c56908590600401615027565b6020604051808303816000875af1158015610c75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c999190615057565b610d0d565b6040516349e5b64960e01b81526001600160a01b038216906349e5b64990610cca908590600401615027565b6020604051808303816000875af1158015610ce9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0d9190615057565b5050610de8565b60ff8516610dcf57606060001960ff881601610d59578460ff16600114610d4657610d418b8986866124a6565b610d52565b610d528b8986866125cd565b9050610dbe565b60ff8716610dbe5760018a6002811115610d7557610d75614e4b565b14610d93576040516386f8e37560e01b815260040160405180910390fd5b8460ff16600114610daf57610daa8b8986866128fe565b610dbb565b610dbb8b898686612b55565b90505b610dc98b84836130ab565b50610de8565b60405163641c695560e01b815260040160405180910390fd5b6040518a907fbce0bd6fef1367dca0b65255a7d010501f79e4dd96d4add4c3e42a419ae6457c90600090a250505050505050505050565b6000333014610e41576040516332b3785760e11b815260040160405180910390fd5b610e4c8484846131dc565b90505b9392505050565b6040516302e2825b60e51b81523360048201527f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b031690635c504b6090602401602060405180830381865afa158015610eba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ede9190615084565b610efa576040516270dbdf60e11b815260040160405180910390fd5b600081806020019051810190610f1091906150e4565b9050806020015151602003610f8b5760008160200151806020019051810190610f39919061515a565b6000818152600360205260408120805492935091610f5690615173565b9091555060405181907ffeea67837572d96738a25f3ac5fa382a1c601ead52e97fb27a02c6103360c06390600090a250505050565b6000808154610f9990615173565b90915550805160008054815260026020908152604090912091909155808201518051610fcb929082018101910161518c565b60008054815260056020908152604080832060019092528220909190610ff18482615296565b5050825161100491906020850190614831565b5050506000547f00000000000000000000000000000000000000000000000000000000000000016001600160401b0316846001600160401b03167f3371afb211a5a616ecaaab76f9466c9295fae2aa4e6dc1ed821b6eb25ee442cf60405160405180910390a45b505050565b60008181526006602090815260408083208054825181850281018501909352808352606094859490939183918301828280156110cb57602002820191906000526020600020905b8154815260200190600101908083116110b7575b505050505093508060020180548060200260200160405190810160405280929190818152602001828054801561112057602002820191906000526020600020905b81548152602001906001019080831161110c575b5050505050925080600501549150509193909250565b6000818152600560209081526040918290208054835181840281018401909452808452606093928301828280156111aa57602002820191906000526020600020906000905b825461010083900a900460ff1681526020600192830181810494850194909303909202910180841161117b5790505b50505050509050919050565b6111df7ff98729ec1ce0343ca1d11c51d1d2d3aa1a7b3f4f6876d0611e0a6fa86520a0cb611a71565b6111e88361146b565b600083815260066020526040902080541580611205575080548214155b15611223576040516344e945a960e01b815260040160405180910390fd5b6005810154156112455760405162aa3fd760e11b815260040160405180910390fd5b60008481526006602052604090206112619060020184846148d7565b50600084815260066020908152604080832042600590910155600290915281205460101c9060ff821660010361134757600086815260016020526040902080546112aa90614fd0565b80601f01602080910402602001604051908101604052809291908181526020018280546112d690614fd0565b80156113235780601f106112f857610100808354040283529160200191611323565b820191906000526020600020905b81548152906001019060200180831161130657829003601f168201915b505050505080602001905181019061133b9190615567565b610100015190506113f9565b6000868152600160205260409020805461136090614fd0565b80601f016020809104026020016040519081016040528092919081815260200182805461138c90614fd0565b80156113d95780601f106113ae576101008083540402835291602001916113d9565b820191906000526020600020905b8154815290600101906020018083116113bc57829003601f168201915b50505050508060200190518101906113f191906156f0565b610100015190505b6000868152600660205260409081902060040180546001600160a01b0319166001600160a01b0384161790555186907f78f133e107c1f55f0cb4abf0d9d0afc7d4949197a40bb9c88b97d51aec80f5cf9061145b9086908990899042906157b6565b60405180910390a2505050505050565b60005481111561148e576040516355da2ca360e11b815260040160405180910390fd5b50565b60006114bc7f6b50fa17b77d24e42e27a04b69fe50cd6967cfb767d18de0bd5fe7e1a32aa8686115e5565b604051632474521560e21b8152600481018590526001600160a01b03848116602483015291909116906391d1485490604401602060405180830381865afa15801561150b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061152f9190615084565b90505b92915050565b6000807f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316636a42b8f86040518163ffffffff1660e01b8152600401602060405180830381865afa158015611599573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115bd919061515a565b9050806000036115e05760405163d0b3066f60e01b815260040160405180910390fd5b919050565b6040516321f8a72160e01b8152600481018290526000907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a721906024015b602060405180830381865afa15801561164e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611532919061583d565b60008280602001905181019061168891906150e4565b855190915060008190036116af576040516324cb170560e01b815260040160405180910390fd5b6116b885613241565b6116c360018361585a565b10156116e257604051635b6b08d760e01b815260040160405180910390fd5b6000838060200190518101906116f8919061586d565b905061171d8760008151811061171057611710614fba565b60200260200101516132d5565b6001600160a01b0316639783d0ef826000015160008151811061174257611742614fba565b60200260200101518a896040518060400160405280896000015181526020018d8a6020015160405160200161177892919061596f565b60408051601f198184030181529181529152516117989190602001615027565b60405160208183030381529060405286602001516000815181106117be576117be614fba565b60200260200101516040518663ffffffff1660e01b81526004016117e59493929190615994565b6000604051808303818588803b1580156117fe57600080fd5b505af1158015611812573d6000803e3d6000fd5b50505050506001821115611a0857611829856132e0565b602084015260015b828160ff161015611a06578760008151811061184f5761184f614fba565b602002602001015160ff16888260ff168151811061186f5761186f614fba565b602002602001015160ff16036118985760405163182d291160e11b815260040160405180910390fd5b6118a36001826159e4565b60ff16158015906118fc5750876118bb6001836159e4565b60ff16815181106118ce576118ce614fba565b602002602001015160ff16888260ff16815181106118ee576118ee614fba565b602002602001015160ff1611155b1561191a576040516322aa062d60e01b815260040160405180910390fd5b611932888260ff168151811061171057611710614fba565b6001600160a01b0316639783d0ef83600001518360ff168151811061195957611959614fba565b60200260200101518b8a886040516020016119749190615027565b60405160208183030381529060405287602001518760ff168151811061199c5761199c614fba565b60200260200101516040518663ffffffff1660e01b81526004016119c39493929190615994565b6000604051808303818588803b1580156119dc57600080fd5b505af11580156119f0573d6000803e3d6000fd5b5050505050806119ff906159fd565b9050611831565b505b5050505050505050565b6040516001600160a01b0383811660248301526044820183905261106b91859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050613312565b611a7b8133611491565b61148e576040516361381e6b60e11b8152600481018290526024015b60405180910390fd5b6000818152600260209081526040808320546001909252822080549192606092909182918291829182918291829190611ad890614fd0565b80601f0160208091040260200160405190810160405280929190818152602001828054611b0490614fd0565b8015611b515780601f10611b2657610100808354040283529160200191611b51565b820191906000526020600020905b815481529060010190602001808311611b3457829003601f168201915b50505050509750611b7560405180604001604052808b81526020018a815250613375565b96508895505050600884901c92505050601082901c601883901c602084901c60c085901c611ba281613241565b6000888152600360205260409020541015611bd057604051635b6b08d760e01b815260040160405180910390fd5b9193959799909294969850565b60ff80851690600886901c811690601087901c90861683148015611bff575081155b611c1c576040516330be21b360e11b815260040160405180910390fd5b6000856002811115611c3057611c30614e4b565b14611c4e576040516353b4315360e11b815260040160405180910390fd5b8360ff168160ff1614611c74576040516330be21b360e11b815260040160405180910390fd5b50505050505050565b6060611c87614912565b611c8f61496e565b8360ff16600103611cb55787806020019051810190611cae9190615567565b9150611cd7565b87806020019051810190611cc991906156f0565b9050611cd4816133a5565b91505b60a0820151518514611cfc5760405163707ea55960e11b815260040160405180910390fd5b611d298686848a7f000000000000000000000000000000000000000000000000000000000000000161359f565b91508360ff16600003611d87578160a00151600081518110611d4d57611d4d614fba565b6020908102919091018101515160a083015152604051611d6f91839101615b28565b60405160208183030381529060405292505050611dac565b81604051602001611d989190615bc8565b604051602081830303815290604052925050505b95945050505050565b6000611dd4604051806040016040528085815260200186815250613375565b9050848114611dfd57600085815260036020526040808220805484845291832091909155868252555b6000868152600160205260409020611e158582615296565b506000868152600460205260409020805483919060ff19166001836002811115611e4157611e41614e4b565b021790555060405186907f144d814d5dc6f17c1a88bc42c55d67392a51c818908ed7cca6118bc51a34b15390600090a2505050505050565b606060008087806020019051810190611e929190615567565b60408101515190915086908114611ebc57604051637753355f60e11b815260040160405180910390fd5b6000805b8281101561201d57898982818110611eda57611eda614fba565b90506020020135600003611f0157604051630f6fa54560e41b815260040160405180910390fd5b611fed611f2d7f494dfdc880823954ed6700117eb435b9bca3643417437b5781c1a89fba6e8b976115e5565b8560c001518381518110611f4357611f43614fba565b60200260200101518e848e8e87818110611f5f57611f5f614fba565b905060200201358d8d88818110611f7857611f78614fba565b9050602002016020810190611f8d919061500a565b8a602001518881518110611fa357611fa3614fba565b60200260200101518b604001518981518110611fc157611fc1614fba565b60200260200101518c608001518a81518110611fdf57611fdf614fba565b60200260200101518b613ae9565b90508560400151838151811061200557612005614fba565b60209081029190910101919091529150600101611ec0565b5080156123b1576000816001600160401b0381111561203e5761203e614a41565b604051908082528060200260200182016040528015612067578160200160208202803683370190505b5090506000826001600160401b0381111561208457612084614a41565b6040519080825280602002602001820160405280156120ad578160200160208202803683370190505b5090506000836001600160401b038111156120ca576120ca614a41565b6040519080825280602002602001820160405280156120f3578160200160208202803683370190505b5090506000846001600160401b0381111561211057612110614a41565b604051908082528060200260200182016040528015612139578160200160208202803683370190505b5090506000856001600160401b0381111561215657612156614a41565b60405190808252806020026020018201604052801561217f578160200160208202803683370190505b5090506000866001600160401b0381111561219c5761219c614a41565b6040519080825280602002602001820160405280156121c5578160200160208202803683370190505b5090506000805b8981101561237f578a6040015181815181106121ea576121ea614fba565b6020026020010151600014612377578a60200151818151811061220f5761220f614fba565b602002602001015188838151811061222957612229614fba565b6020026020010181815250508a60400151818151811061224b5761224b614fba565b602002602001015187838151811061226557612265614fba565b6020026020010181815250508a60600151818151811061228757612287614fba565b60200260200101518683815181106122a1576122a1614fba565b6020026020010181815250508a6080015181815181106122c3576122c3614fba565b60200260200101518583815181106122dd576122dd614fba565b6020026020010181815250508a60c0015181815181106122ff576122ff614fba565b602002602001015184838151811061231957612319614fba565b6020026020010190151590811515815250508a60e00151818151811061234157612341614fba565b602002602001015183838151811061235b5761235b614fba565b9115156020928302919091019091015261237482615173565b91505b6001016121cc565b5050602089019590955260408801939093526060870191909152608086015260c085015260e0840152600193506123b6565b600293505b826040516020016123c79190615bc8565b6040516020818303038152906040529450505050965096945050505050565b6060600080858060200190518101906123ff91906156f0565b90508460000361242257604051630f6fa54560e41b815260040160405180910390fd5b61246e61244e7f494dfdc880823954ed6700117eb435b9bca3643417437b5781c1a89fba6e8b976115e5565b8260c0015189600089898760200151886040015189608001516000613ae9565b50604080840192909252905190925061248b908290602001615b28565b60405160208183030381529060405292505094509492505050565b60606000848060200190518101906124be91906156f0565b6040805160208082018a905260008284015282518083038401815260609092019092526101208301528101519091506124f690613e80565b6125135760405163a412f06560e01b815260040160405180910390fd5b6125208160200151613f19565b6001600160a01b031663ef164fef8286866040518463ffffffff1660e01b815260040161254f93929190615cdb565b6020604051808303816000875af192505050801561258a575060408051601f3d908101601f191682019092526125879181019061515a565b60015b6125b2576125aa8482600001516001600285602001518660400151613f2d565b9150506125c5565b5050506040805160208101909152600081525b949350505050565b60606000848060200190518101906125e59190615567565b6020810151519091506000908161261b7fbcc180fb907e9ae431665de4bc74305c00b7b27442aadd477980ecc4bb14c0116115e5565b905060005b828110156128b457816001600160a01b031663b5c756978660200151838151811061264d5761264d614fba565b60200260200101516040518263ffffffff1660e01b815260040161267391815260200190565b602060405180830381865afa158015612690573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b49190615084565b6126d15760405163a412f06560e01b815260040160405180910390fd5b6126f7856020015182815181106126ea576126ea614fba565b6020026020010151613f19565b6001600160a01b031663ef164fef604051806101400160405280886000015181526020018860200151858151811061273157612731614fba565b602002602001015181526020018860400151858151811061275457612754614fba565b602002602001015181526020018860600151858151811061277757612777614fba565b602002602001015181526020018860800151858151811061279a5761279a614fba565b602002602001015181526020018860a0015185815181106127bd576127bd614fba565b602002602001015181526020016000151581526020016000151581526020018861010001516001600160a01b031681526020018d8560405160200161280c929190918252602082015260400190565b6040516020818303038152906040528152508a8a6040518463ffffffff1660e01b815260040161283e93929190615cdb565b6020604051808303816000875af1925050508015612879575060408051601f3d908101601f191682019092526128769181019061515a565b60015b61288657600193506128ac565b5060008560400151828151811061289f5761289f614fba565b6020026020010181815250505b600101612620565b5082156128e2576128d7878560000151600160028860200151896040015161405d565b9450505050506125c5565b5050604080516020810190915260008152979650505050505050565b606060008480602001905181019061291691906156f0565b905060006129278260200151613f19565b90506000612934826140cc565b60408481015190516370a0823160e01b815230600482015291925082916001600160a01b038316906370a0823190602401602060405180830381865afa158015612982573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129a6919061515a565b10612b3c5760408401516129c6906001600160a01b03831690859061410c565b604051634af278ed60e11b81526001600160a01b038416906395e4f1da906129f69087908b908b90600401615cdb565b6020604051808303816000875af1925050508015612a31575060408051601f3d908101601f19168201909252612a2e9181019061515a565b60015b612afc576040840151612a50906001600160a01b03831690859061419c565b60008981526006602090815260408083208783015181546001808201845583875285872090910191909155808201805480830182559086528486200180546001600160a01b0319166001600160a01b03891617905560039091018054918201815584528284209281049092018054601f9093166101000a60ff0219909216909155518a917f21c4f33a94342256a428d6cb08476047bdb16e6866308b7d904df8990eb781c891a26128e2565b8015801590612b0d57508460e00151155b15612b3657612b2a88866000015160006001896020015186613f2d565b955050505050506125c5565b506128e2565b604051630399226960e41b815260040160405180910390fd5b6060600084806020019051810190612b6d9190615567565b90506000612b7e8260200151614259565b6020830151519091506000908180805b8381101561302b5786604001518181518110612bac57612bac614fba565b602002602001015160001461302357612bdd868281518110612bd057612bd0614fba565b60200260200101516140cc565b945086604001518181518110612bf557612bf5614fba565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa158015612c44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c68919061515a565b10612b3c57612cc1868281518110612c8257612c82614fba565b602002602001015188604001518381518110612ca057612ca0614fba565b6020026020010151876001600160a01b031661410c9092919063ffffffff16565b612cc96149c9565b868281518110612cdb57612cdb614fba565b60200260200101516001600160a01b03166395e4f1da6040518061014001604052808b6000015181526020018b602001518681518110612d1d57612d1d614fba565b602002602001015181526020018b604001518681518110612d4057612d40614fba565b602002602001015181526020018b606001518681518110612d6357612d63614fba565b602002602001015181526020018b608001518681518110612d8657612d86614fba565b602002602001015181526020018481526020016000151581526020018b60e001518681518110612db857612db8614fba565b6020026020010151151581526020018b61010001516001600160a01b031681526020018b61012001518152508d8d6040518463ffffffff1660e01b8152600401612e0493929190615cdb565b6020604051808303816000875af1925050508015612e3f575060408051601f3d908101601f19168201909252612e3c9181019061515a565b60015b612f9f57612e97878381518110612e5857612e58614fba565b602002602001015189604001518481518110612e7657612e76614fba565b6020026020010151886001600160a01b031661419c9092919063ffffffff16565b60008d81526006602090815260409091209089015180516001955084908110612ec257612ec2614fba565b60209081029190910181015182546001810184556000938452918320909101556040890151805184908110612ef957612ef9614fba565b602002602001018181525050600660008e8152602001908152602001600020600101612f30888481518110612bd057612bd0614fba565b8154600180820184556000938452602080852090920180546001600160a01b0319166001600160a01b0394909416939093179092558f83526006815260408320600301805492830181558352918290209181049091018054601f9092166101000a60ff02199091169055613021565b8015801590612fc957508860e001518381518110612fbf57612fbf614fba565b6020026020010151155b15612ffa57600194508089604001518481518110612fe957612fe9614fba565b60200260200101818152505061301f565b60008960400151848151811061301257613012614fba565b6020026020010181815250505b505b505b600101612b8e565b50801561305e576040518b907f21c4f33a94342256a428d6cb08476047bdb16e6866308b7d904df8990eb781c890600090a25b811561308d57613080898760000151600060018a602001518b6040015161405d565b96505050505050506125c5565b50506040805160208101909152600081529998505050505050505050565b80511561106b5760008381526005602090815260408083208054825181850281018501909352808352919290919083018282801561312657602002820191906000526020600020906000905b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116130f75790505b5050505050905060006131587fab437a16135e856111e538dc45051dd9c2778c6069d25a22fb9ac4766c356aa16115e5565b6001600160a01b0316633283166a8584866040518463ffffffff1660e01b815260040161318793929190615d17565b600060405180830381865afa1580156131a4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526131cc9190810190615d4b565b9150506105653383868685611672565b6000828411156131ff5760405163c8a403d160e01b815260040160405180910390fd5b600061271061320e848261585a565b6132189086615d87565b6132229190615d9e565b905080851015613236576000915050610e4f565b506001949350505050565b604051631049a0db60e01b81526001600160401b03821660048201526000907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b031690631049a0db90602401602060405180830381865afa1580156132b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611532919061515a565b60006115328261430b565b606081805190602001206040516020016132fc91815260200190565b6040516020818303038152906040529050919050565b60006133276001600160a01b0384168361435d565b9050805160001415801561334c57508080602001905181019061334a9190615084565b155b1561106b57604051635274afe760e01b81526001600160a01b0384166004820152602401611a97565b6000816040516020016133889190615027565b604051602081830303815290604052805190602001209050919050565b6133ad614912565b604080516001808252818301909252600091602080830190803683370190505090508260200151816000815181106133e7576133e7614fba565b602090810291909101015260408051600180825281830190925260009181602001602082028036833701905050905083604001518160008151811061342e5761342e614fba565b602090810291909101015260408051600180825281830190925260009181602001602082028036833701905050905084606001518160008151811061347557613475614fba565b60209081029190910101526040805160018082528183019092526000918160200160208202803683370190505090508560800151816000815181106134bc576134bc614fba565b6020908102919091010152604080516001808252818301909252600091816020015b6134e66149c9565b8152602001906001900390816134de5790505090508660a001518160008151811061351357613513614fba565b60200260200101819052506040518061014001604052808860000151815260200186815260200185815260200184815260200183815260200182815260200161355f8960c0015161436b565b81526020016135718960e0015161436b565b81526020018861010001516001600160a01b0316815260200188610120015181525095505050505050919050565b6135a7614912565b60a0840151516000805b82811015613adc578888828181106135cb576135cb614fba565b90506020028101906135dd9190615dc0565b158015915061360e57508660a0015181815181106135fd576135fd614fba565b602002602001015160000151516000145b15613ad45761362c876020015182815181106126ea576126ea614fba565b9150613637306143b6565b60ff16826001600160a01b03166391deb8826040518163ffffffff1660e01b8152600401602060405180830381865afa158015613678573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061369c9190615e06565b60ff1603613ad4576136ca8760a0015182815181106136bd576136bd614fba565b6020026020010151614445565b60007f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b031663e85b2b548960a00151848151811061371157613711614fba565b6020026020010151606001516040518263ffffffff1660e01b8152600401613742919060ff91909116815260200190565b602060405180830381865afa15801561375f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613783919061583d565b9050806001600160a01b031663c87439eb6040518061012001604052808d8d878181106137b2576137b2614fba565b90506020028101906137c49190615dc0565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506001600160401b03808b1660208301528b16604082015260a08c015180516060909201918790811061382f5761382f614fba565b6020026020010151608001516001600160401b03168152602001600015158152602001866001600160a01b031681526020018b61010001516001600160a01b0316815260200161387e876140cc565b6001600160a01b0316815260006020909101526040516001600160e01b031960e084901b1681526138b29190600401615e23565b602060405180830381865afa1580156138cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f39190615084565b50613a3a816001600160a01b0316639bbbb5c88c8c8681811061391857613918614fba565b905060200281019061392a9190615dc0565b60006040518463ffffffff1660e01b815260040161394a93929190615ef6565b602060405180830381865afa158015613967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061398b919061515a565b846001600160a01b031663b7ba28cd8b6040015186815181106139b0576139b0614fba565b60200260200101516040518263ffffffff1660e01b81526004016139d691815260200190565b602060405180830381865afa1580156139f3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a17919061515a565b8a608001518581518110613a2d57613a2d614fba565b60200260200101516131dc565b613a57576040516358d0562960e11b815260040160405180910390fd5b898983818110613a6957613a69614fba565b9050602002810190613a7b9190615dc0565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050505060a0890151805184908110613ac657613ac6614fba565b602090810291909101015152505b6001016135b1565b5094979650505050505050565b600080806001600160a01b038816613b14576040516331b5a77960e11b815260040160405180910390fd5b60008c15613cf757898e6001600160a01b031663c830c85a8e8e6040518363ffffffff1660e01b8152600401613b54929190918252602082015260400190565b602060405180830381865afa158015613b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b95919061515a565b14613cf7576000808f6001600160a01b03166395c2c5d78f8f6040518363ffffffff1660e01b8152600401613bd4929190918252602082015260400190565b6040805180830381865afa158015613bf0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c149190615f2e565b915091508b8114613c38576040516320590e3d60e11b815260040160405180910390fd5b8a6001600160a01b0316826001600160a01b031614613c6a576040516325bfc2e360e11b815260040160405180910390fd5b5060008d815260066020908152604082208054600181810183558285528385209091018d9055818101805480830182559085528385200180546001600160a01b039096166001600160a01b03199096169590951790945560030180548085018255908352818320918104909101805460ff601f9093166101000a9283021916909117905597506002935090505b80613e6b5760405163803c15df60e01b8152600481018b90526024810188905260448101879052309063803c15df90606401602060405180830381865afa925050508015613d62575060408051601f3d908101601f19168201909252613d5f91810190615084565b60015b613d6f5760019250613d7f565b8015613d7d578a9750600193505b505b613d8888613e80565b8015613da557506001836002811115613da357613da3614e4b565b145b613e525760008c815260066020908152604082208054600181810183559184529183209091018a9055613ddb908a908c9061447e565b60008e815260066020908152604082206001808201805480830182559085528385200180546001600160a01b0319166001600160a01b039690961695909517909455600301805493840181558252808220908304018054601f9093166101000a60ff0219909216909155975060029350613e6b9050565b613e5e888a600061447e565b50613e6885615173565b94505b50949c909b5091995090975050505050505050565b6000613eab7fbcc180fb907e9ae431665de4bc74305c00b7b27442aadd477980ecc4bb14c0116115e5565b6001600160a01b031663b5c75697836040518263ffffffff1660e01b8152600401613ed891815260200190565b602060405180830381865afa158015613ef5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115329190615084565b6000613f2482614565565b50909392505050565b60606040518060400160405280613fe6876001811115613f4f57613f4f614e4b565b876002811115613f6157613f61614e4b565b6000613f6c306143b6565b8d7f000000000000000000000000000000000000000000000000000000000000000160ff9590951660089490941b61ff00169390931760109290921b62ff0000169190911760189190911b63ff000000161760209190911b640100000000600160c01b03161760c09190911b6001600160c01b0319161790565b815260408051606080820183528a8252602082810189815292840188815284518083018e90529351948401949094529251908201529101906080015b60408051601f198184030181529181529152516140429190602001615027565b60405160208183030381529060405290509695505050505050565b6060604051806040016040528061409c87600181111561407f5761407f614e4b565b87600281111561409157614091614e4b565b6001613f6c306143b6565b81526020016040518060600160405280898152602001868152602001858152506040516020016140229190615f5c565b6000816001600160a01b031663b60262ca6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561164e573d6000803e3d6000fd5b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa15801561415c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614180919061515a565b905061419684846141918585614fa7565b614599565b50505050565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa1580156141ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614210919061515a565b90508181101561424c5760405163e570110f60e01b81526001600160a01b03841660048201526024810182905260448101839052606401611a97565b6141968484848403614599565b8051606090806001600160401b0381111561427657614276614a41565b60405190808252806020026020018201604052801561429f578160200160208202803683370190505b50915060005b81811015614304576142cf8482815181106142c2576142c2614fba565b6020026020010151614565565b9050508382815181106142e4576142e4614fba565b6001600160a01b03909216602092830291909101909101526001016142a5565b5050919050565b604051630eff125d60e01b815260ff821660048201526000907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b031690630eff125d90602401611631565b606061152f83836000614629565b6040805160018082528183019092526060916020808301908036833701905050905081816000815181106143a1576143a1614fba565b91151560209283029190910190910152919050565b604051632f6438ab60e01b81526001600160a01b0382811660048301526000917f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a251490911690632f6438ab90602401602060405180830381865afa158015614421573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115329190615e06565b60208101516001600160a01b03161580614460575080515115155b1561148e57604051630c57767d60e41b815260040160405180910390fd5b600061448984613f19565b6001600160a01b031663b60262ca6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156144e2575060408051601f3d908101601f191682019092526144df9181019061583d565b60015b15614527578280156145065750836001600160a01b0316816001600160a01b031614155b15614524576040516325bfc2e360e11b815260040160405180910390fd5b90505b811580156145475750826001600160a01b0316816001600160a01b031614155b15610e4f576040516325bfc2e360e11b815260040160405180910390fd5b8060a081901c60c082901c60008190036145925760405163030042b760e01b815260040160405180910390fd5b9193909250565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b1790526145ea84826146c6565b614196576040516001600160a01b0384811660248301526000604483015261461f91869182169063095ea7b390606401611a3f565b6141968482613312565b60608147101561464e5760405163cd78605960e01b8152306004820152602401611a97565b600080856001600160a01b0316848660405161466a9190615f9f565b60006040518083038185875af1925050503d80600081146146a7576040519150601f19603f3d011682016040523d82523d6000602084013e6146ac565b606091505b50915091506146bc868383614769565b9695505050505050565b6000806000846001600160a01b0316846040516146e39190615f9f565b6000604051808303816000865af19150503d8060008114614720576040519150601f19603f3d011682016040523d82523d6000602084013e614725565b606091505b509150915081801561474f57508051158061474f57508080602001905181019061474f9190615084565b8015611dac5750505050506001600160a01b03163b151590565b60608261477e57614779826147c5565b610e4f565b815115801561479557506001600160a01b0384163b155b156147be57604051639996b31560e01b81526001600160a01b0385166004820152602401611a97565b5080610e4f565b8051156147d55780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b508054600082559060005260206000209081019061148e91906149fe565b50805460008255601f01602090049060005260206000209081019061148e91906149fe565b82805482825590600052602060002090601f016020900481019282156148c75791602002820160005b8382111561489857835183826101000a81548160ff021916908360ff160217905550926020019260010160208160000104928301926001030261485a565b80156148c55782816101000a81549060ff0219169055600101602081600001049283019260010302614898565b505b506148d39291506149fe565b5090565b8280548282559060005260206000209081019282156148c7579160200282015b828111156148c75782358255916020019190600101906148f7565b604051806101400160405280600081526020016060815260200160608152602001606081526020016060815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001606081525090565b60405180610140016040528060008152602001600081526020016000815260200160008152602001600081526020016149a56149c9565b81526000602082018190526040820181905260608083019190915260809091015290565b6040805160c081018252606080825260006020830181905292820183905281018290526080810182905260a081019190915290565b5b808211156148d357600081556001016149ff565b600060208284031215614a2557600080fd5b5035919050565b6001600160a01b038116811461148e57600080fd5b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715614a7957614a79614a41565b60405290565b60405161014081016001600160401b0381118282101715614a7957614a79614a41565b604051601f8201601f191681016001600160401b0381118282101715614aca57614aca614a41565b604052919050565b60006001600160401b03821115614aeb57614aeb614a41565b5060051b60200190565b60ff8116811461148e57600080fd5b6001600160401b038116811461148e57600080fd5b80356115e081614b04565b60006001600160401b03821115614b3d57614b3d614a41565b50601f01601f191660200190565b600082601f830112614b5c57600080fd5b8135614b6f614b6a82614b24565b614aa2565b818152846020838601011115614b8457600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a08688031215614bb957600080fd5b8535614bc481614a2c565b94506020868101356001600160401b0380821115614be157600080fd5b818901915089601f830112614bf557600080fd5b8135614c03614b6a82614ad2565b81815260059190911b8301840190848101908c831115614c2257600080fd5b938501935b82851015614c49578435614c3a81614af5565b82529385019390850190614c27565b9850614c5a91505060408a01614b19565b95506060890135925080831115614c7057600080fd5b614c7c8a848b01614b4b565b94506080890135925080831115614c9257600080fd5b5050614ca088828901614b4b565b9150509295509295909350565b60005b83811015614cc8578181015183820152602001614cb0565b50506000910152565b60008151808452614ce9816020860160208601614cad565b601f01601f19169290920160200192915050565b60208152600061152f6020830184614cd1565b60008083601f840112614d2257600080fd5b5081356001600160401b03811115614d3957600080fd5b6020830191508360208260051b8501011115614d5457600080fd5b9250929050565b600080600060408486031215614d7057600080fd5b8335925060208401356001600160401b03811115614d8d57600080fd5b614d9986828701614d10565b9497909650939450505050565b600080600080600060608688031215614dbe57600080fd5b8535945060208601356001600160401b0380821115614ddc57600080fd5b614de889838a01614d10565b90965094506040880135915080821115614e0157600080fd5b50614e0e88828901614d10565b969995985093965092949392505050565b600080600060608486031215614e3457600080fd5b505081359360208301359350604090920135919050565b634e487b7160e01b600052602160045260246000fd5b6020810160038310614e8357634e487b7160e01b600052602160045260246000fd5b91905290565b60008060408385031215614e9c57600080fd5b8235614ea781614b04565b915060208301356001600160401b03811115614ec257600080fd5b614ece85828601614b4b565b9150509250929050565b60008151808452602080850194506020840160005b83811015614f0957815187529582019590820190600101614eed565b509495945050505050565b606081526000614f276060830186614ed8565b8281036020840152614f398186614ed8565b915050826040830152949350505050565b60008151808452602080850194506020840160005b83811015614f0957815160ff1687529582019590820190600101614f5f565b60208152600061152f6020830184614f4a565b634e487b7160e01b600052601160045260246000fd5b8082018082111561153257611532614f91565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680614fe457607f821691505b60208210810361500457634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561501c57600080fd5b8135610e4f81614a2c565b6020815281516020820152600060208301516040808401526125c56060840182614cd1565b80516115e081614b04565b60006020828403121561506957600080fd5b8151610e4f81614b04565b805180151581146115e057600080fd5b60006020828403121561509657600080fd5b61152f82615074565b600082601f8301126150b057600080fd5b81516150be614b6a82614b24565b8181528460208386010111156150d357600080fd5b6125c5826020830160208701614cad565b6000602082840312156150f657600080fd5b81516001600160401b038082111561510d57600080fd5b908301906040828603121561512157600080fd5b615129614a57565b8251815260208301518281111561513f57600080fd5b61514b8782860161509f565b60208301525095945050505050565b60006020828403121561516c57600080fd5b5051919050565b60006001820161518557615185614f91565b5060010190565b6000806040838503121561519f57600080fd5b82516001600160401b03808211156151b657600080fd5b818501915085601f8301126151ca57600080fd5b815160206151da614b6a83614ad2565b82815260059290921b840181019181810190898411156151f957600080fd5b948201945b8386101561522057855161521181614af5565b825294820194908201906151fe565b9188015191965090935050508082111561523957600080fd5b50614ece8582860161509f565b601f82111561106b576000816000526020600020601f850160051c8101602086101561526f5750805b601f850160051c820191505b8181101561528e5782815560010161527b565b505050505050565b81516001600160401b038111156152af576152af614a41565b6152c3816152bd8454614fd0565b84615246565b602080601f8311600181146152f857600084156152e05750858301515b600019600386901b1c1916600185901b17855561528e565b600085815260208120601f198616915b8281101561532757888601518255948401946001909101908401615308565b50858210156153455787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600082601f83011261536657600080fd5b81516020615376614b6a83614ad2565b8083825260208201915060208460051b87010193508684111561539857600080fd5b602086015b848110156153b4578051835291830191830161539d565b509695505050505050565b80516115e081614a2c565b600060c082840312156153dc57600080fd5b60405160c081016001600160401b0382821081831117156153ff576153ff614a41565b81604052829350845191508082111561541757600080fd5b506154248582860161509f565b825250602083015161543581614a2c565b6020820152604083015161544881614a2c565b6040820152606083015161545b81614af5565b606082015261546c6080840161504c565b608082015260a083015160a08201525092915050565b600082601f83011261549357600080fd5b815160206154a3614b6a83614ad2565b82815260059290921b840181019181810190868411156154c257600080fd5b8286015b848110156153b45780516001600160401b038111156154e55760008081fd5b6154f38986838b01016153ca565b8452509183019183016154c6565b600082601f83011261551257600080fd5b81516020615522614b6a83614ad2565b8083825260208201915060208460051b87010193508684111561554457600080fd5b602086015b848110156153b45761555a81615074565b8352918301918301615549565b60006020828403121561557957600080fd5b81516001600160401b038082111561559057600080fd5b9083019061014082860312156155a557600080fd5b6155ad614a7f565b825181526020830151828111156155c357600080fd5b6155cf87828601615355565b6020830152506040830151828111156155e757600080fd5b6155f387828601615355565b60408301525060608301518281111561560b57600080fd5b61561787828601615355565b60608301525060808301518281111561562f57600080fd5b61563b87828601615355565b60808301525060a08301518281111561565357600080fd5b61565f87828601615482565b60a08301525060c08301518281111561567757600080fd5b61568387828601615501565b60c08301525060e08301518281111561569b57600080fd5b6156a787828601615501565b60e0830152506101006156bb8185016153bf565b9082015261012083810151838111156156d357600080fd5b6156df8882870161509f565b918301919091525095945050505050565b60006020828403121561570257600080fd5b81516001600160401b038082111561571957600080fd5b90830190610140828603121561572e57600080fd5b615736614a7f565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a08301518281111561577457600080fd5b615780878286016153ca565b60a08301525061579260c08401615074565b60c08201526157a360e08401615074565b60e08201526101006156bb8185016153bf565b600060608201606083528087548083526080850191508860005260209250602060002060005b828110156157f8578154845292840192600191820191016157dc565b50505083810360208501528581526001600160fb1b0386111561581a57600080fd5b8560051b9150818760208301376040939093019390935250016020019392505050565b60006020828403121561584f57600080fd5b8151610e4f81614a2c565b8181038181111561153257611532614f91565b6000602080838503121561588057600080fd5b82516001600160401b038082111561589757600080fd5b90840190604082870312156158ab57600080fd5b6158b3614a57565b8251828111156158c257600080fd5b6158ce88828601615355565b82525083830151828111156158e257600080fd5b80840193505086601f8401126158f757600080fd5b8251615905614b6a82614ad2565b81815260059190911b8401850190858101908983111561592457600080fd5b8686015b8381101561595c578051868111156159405760008081fd5b61594e8c8a838b010161509f565b845250918701918701615928565b5095830195909552509695505050505050565b6040815260006159826040830185614f4a565b8281036020840152611dac8185614cd1565b6001600160a01b03851681526001600160401b03841660208201526080604082018190526000906159c790830185614cd1565b82810360608401526159d98185614cd1565b979650505050505050565b60ff828116828216039081111561153257611532614f91565b600060ff821660ff8103615a1357615a13614f91565b60010192915050565b6000815160c08452615a3160c0850182614cd1565b9050602083015160018060a01b038082166020870152806040860151166040870152505060ff60608401511660608501526001600160401b03608084015116608085015260a083015160a08501528091505092915050565b6000610140825184526020830151602085015260408301516040850152606083015160608501526080830151608085015260a08301518160a0860152615ad182860182615a1c565b91505060c0830151615ae760c086018215159052565b5060e0830151615afb60e086018215159052565b50610100838101516001600160a01b03169085015261012080840151858303828701526146bc8382614cd1565b60208152600061152f6020830184615a89565b60008282518085526020808601955060208260051b8401016020860160005b84811015615b8857601f19868403018952615b76838351615a1c565b98840198925090830190600101615b5a565b5090979650505050505050565b60008151808452602080850194506020840160005b83811015614f09578151151587529582019590820190600101615baa565b602081528151602082015260006020830151610140806040850152615bf1610160850183614ed8565b91506040850151601f1980868503016060870152615c0f8483614ed8565b93506060870151915080868503016080870152615c2c8483614ed8565b935060808701519150808685030160a0870152615c498483614ed8565b935060a08701519150808685030160c0870152615c668483615b3b565b935060c08701519150808685030160e0870152615c838483615b95565b935060e08701519150610100818786030181880152615ca28584615b95565b945080880151925050610120615cc2818801846001600160a01b03169052565b8701518685039091018387015290506146bc8382614cd1565b606081526000615cee6060830186615a89565b6001600160a01b03949094166020830152506001600160401b0391909116604090910152919050565b6001600160401b0384168152606060208201526000615d396060830185614f4a565b82810360408401526146bc8185614cd1565b60008060408385031215615d5e57600080fd5b8251915060208301516001600160401b03811115615d7b57600080fd5b614ece8582860161509f565b808202811582820484141761153257611532614f91565b600082615dbb57634e487b7160e01b600052601260045260246000fd5b500490565b6000808335601e19843603018112615dd757600080fd5b8301803591506001600160401b03821115615df157600080fd5b602001915036819003821315614d5457600080fd5b600060208284031215615e1857600080fd5b8151610e4f81614af5565b6020815260008251610120806020850152615e42610140850183614cd1565b91506020850151615e5e60408601826001600160401b03169052565b5060408501516001600160401b03811660608601525060608501516001600160401b038116608086015250608085015180151560a08601525060a08501516001600160a01b03811660c08601525060c08501516001600160a01b03811660e08601525060e0850151610100615edd818701836001600160a01b03169052565b909501516001600160a01b031693019290925250919050565b6040815282604082015282846060830137600060608483018101919091529115156020820152601f909201601f191690910101919050565b60008060408385031215615f4157600080fd5b8251615f4c81614a2c565b6020939093015192949293505050565b60208152815160208201526000602083015160606040840152615f826080840182614ed8565b90506040840151601f19848303016060850152611dac8282614ed8565b60008251615fb1818460208701614cad565b919091019291505056fea2646970667358221220374638a3255ecd4b127cbbc75e1971d2594ffd45b6f30f95ddae7ab6ec7214fd64736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a2514
-----Decoded View---------------
Arg [0] : superRegistry_ (address): 0x17A332dC7B40aE701485023b219E9D6f493a2514
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a2514
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
BASE | 22.49% | $3,264.7 | 0.8517 | $2,780.69 | |
BASE | 9.88% | $0.999213 | 1,222.285 | $1,221.32 | |
BASE | 5.16% | $3,529.82 | 0.1808 | $638.16 | |
BASE | 3.14% | $3,272.82 | 0.1188 | $388.8 | |
BASE | 1.06% | $0.998685 | 130.646 | $130.47 | |
BASE | 0.44% | $1 | 53.8616 | $53.86 | |
BASE | 0.23% | $1.42 | 19.8598 | $28.2 | |
BASE | 0.11% | $0.026835 | 527.4609 | $14.15 | |
BASE | 0.09% | $3,661.72 | 0.00290343 | $10.63 | |
BASE | 0.01% | $0.006977 | 209.2842 | $1.46 | |
BASE | <0.01% | <$0.000001 | 35,523,552 | $0.5293 | |
MATIC | 8.58% | $0.998962 | 1,062.1657 | $1,061.06 | |
MATIC | 3.17% | $1 | 391.4571 | $391.46 | |
MATIC | 2.83% | $0.998724 | 350.4676 | $350.02 | |
MATIC | 1.67% | $0.529916 | 388.8342 | $206.05 | |
MATIC | 1.05% | $3,273.86 | 0.0395 | $129.23 | |
MATIC | 0.03% | $0.998962 | 3.4552 | $3.45 | |
MATIC | <0.01% | $0.000016 | 55,252.6231 | $0.8934 | |
MATIC | <0.01% | $1.18 | 0.6622 | $0.7813 | |
MATIC | <0.01% | $0.529352 | 0.6554 | $0.346921 | |
MATIC | <0.01% | $1.08 | 0.32 | $0.3446 | |
OP | 8.90% | $0.99992 | 1,100.7078 | $1,100.62 | |
OP | 3.77% | $3,270.66 | 0.1425 | $466.08 | |
OP | 0.46% | $3,844.1 | 0.0147 | $56.56 | |
OP | 0.40% | $1.63 | 30.3082 | $49.41 | |
OP | 0.24% | $0.99992 | 29.8615 | $29.86 | |
OP | 0.22% | $59,745 | 0.0004615 | $27.57 | |
OP | 0.04% | $0.998756 | 5.0673 | $5.06 | |
OP | <0.01% | $0.999722 | 0.2518 | $0.2517 | |
OP | <0.01% | $13.69 | 0.0144 | $0.1971 | |
OP | <0.01% | $0.388841 | 0.4418 | $0.1717 | |
OP | <0.01% | $3,273.73 | 0.00002367 | $0.077488 | |
ARB | 5.44% | $0.998179 | 673.5366 | $672.31 | |
ARB | 3.32% | $0.998591 | 411.4597 | $410.88 | |
ARB | 3.18% | $3,265.43 | 0.1204 | $393.02 | |
ARB | 0.85% | $0.754953 | 138.5009 | $104.56 | |
ARB | 0.38% | $0.99579 | 47.6124 | $47.41 | |
ARB | 0.31% | $0.998591 | 38.2738 | $38.22 | |
ARB | 0.15% | $59,686 | 0.00031412 | $18.75 | |
ARB | 0.15% | $3.94 | 4.7294 | $18.63 | |
ARB | 0.10% | $3,834.77 | 0.00334028 | $12.81 | |
ARB | 0.04% | $1.06 | 4.9479 | $5.26 | |
ARB | 0.02% | $1 | 2.6804 | $2.68 | |
ARB | 0.01% | $3,273.73 | 0.0005409 | $1.77 | |
ARB | 0.01% | $0.070383 | 21.0145 | $1.48 | |
ARB | 0.01% | $8.46 | 0.1533 | $1.3 | |
ARB | <0.01% | $3,634.92 | 0.00002992 | $0.1087 | |
ETH | 11.67% | $3,276.06 | 0.4404 | $1,442.84 | |
ETH | 0.08% | $1 | 9.606 | $9.63 | |
ETH | 0.05% | $0.999651 | 5.9753 | $5.97 | |
ETH | <0.01% | $3,276.06 | 0.00029606 | $0.969905 | |
AVAX | 0.09% | $0.998572 | 10.7665 | $10.75 | |
AVAX | 0.09% | $26.55 | 0.4 | $10.62 | |
AVAX | 0.03% | $0.324262 | 11.7584 | $3.81 | |
BSC | <0.01% | $1 | 1.15 | $1.15 | |
BSC | <0.01% | $0.117542 | 6.2108 | $0.73 | |
BSC | <0.01% | $0.99579 | 0.5845 | $0.582 |
Loading...
Loading
[ Download: CSV Export ]
[ 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.