More Info
Private Name Tags
ContractCreator
Multichain Info
7 addresses found via
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
18264480 | 23 hrs ago | 0.00007667 ETH | ||||
18264480 | 23 hrs ago | 0.00003034 ETH | ||||
18227953 | 43 hrs ago | 0.00008507 ETH | ||||
18227953 | 43 hrs ago | 0.00003313 ETH | ||||
18166839 | 3 days ago | 0.00041104 ETH | ||||
18166839 | 3 days ago | 0.00004045 ETH | ||||
18153377 | 3 days ago | 0.00016547 ETH | ||||
18153377 | 3 days ago | 0.00008576 ETH | ||||
18134012 | 3 days ago | 0.00008542 ETH | ||||
18134012 | 3 days ago | 0.00003463 ETH | ||||
18134012 | 3 days ago | 0.00012005 ETH | ||||
18133568 | 3 days ago | 0.00008541 ETH | ||||
18133568 | 3 days ago | 0.00003459 ETH | ||||
18133568 | 3 days ago | 0.00012 ETH | ||||
18133293 | 3 days ago | 0.0000851 ETH | ||||
18133293 | 3 days ago | 0.00003357 ETH | ||||
18133293 | 3 days ago | 0.00011867 ETH | ||||
18133011 | 4 days ago | 0.0000851 ETH | ||||
18133011 | 4 days ago | 0.00003357 ETH | ||||
18133011 | 4 days ago | 0.00011867 ETH | ||||
18121680 | 4 days ago | 0.00008577 ETH | ||||
18121680 | 4 days ago | 0.00003455 ETH | ||||
18121074 | 4 days ago | 0.00008545 ETH | ||||
18121074 | 4 days ago | 0.00003391 ETH | ||||
18120122 | 4 days ago | 0.0000854 ETH |
Loading...
Loading
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0x80AAb0eA...5900e906d The constructor portion of the code might be different and could alter the actual behaviour of the contract
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", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"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"}]
Deployed Bytecode
0x6080604052600436106101095760003560e01c80635aef948011610095578063cc2d8abd11610064578063cc2d8abd1461033e578063d468711a1461035e578063d49616061461038d578063d830364e146103ba578063e17d89e8146103e757600080fd5b80635aef948014610272578063803c15df1461028557806385e1f4d0146102b5578063b63d36a51461030157600080fd5b80632d46647d116100dc5780632d46647d146101b8578063361ad42b146101d857806336445ffd14610205578063439890e214610232578063474fd8741461025257600080fd5b806313bff0121461010e57806313c02a591461013057806323de31e11461015957806324c73dda1461016c575b600080fd5b34801561011a57600080fd5b5061012e610129366004614a13565b610407565b005b34801561013c57600080fd5b5061014660005481565b6040519081526020015b60405180910390f35b61012e610167366004614ba1565b6104fe565b34801561017857600080fd5b506101a07f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a251481565b6040516001600160a01b039091168152602001610150565b3480156101c457600080fd5b5061012e6101d3366004614a13565b61056c565b3480156101e457600080fd5b506101f86101f3366004614a13565b610815565b6040516101509190614cfd565b34801561021157600080fd5b50610146610220366004614a13565b60026020526000908152604090205481565b34801561023e57600080fd5b5061012e61024d366004614d5b565b6108af565b34801561025e57600080fd5b5061012e61026d366004614da6565b610980565b61012e610280366004614a13565b610afb565b34801561029157600080fd5b506102a56102a0366004614e1f565b610e1f565b6040519015158152602001610150565b3480156102c157600080fd5b506102e97f0000000000000000000000000000000000000000000000000000000000013e3181565b6040516001600160401b039091168152602001610150565b34801561030d57600080fd5b5061033161031c366004614a13565b60046020526000908152604090205460ff1681565b6040516101509190614e61565b34801561034a57600080fd5b5061012e610359366004614e89565b610e56565b34801561036a57600080fd5b5061037e610379366004614a13565b611070565b60405161015093929190614f14565b34801561039957600080fd5b506101466103a8366004614a13565b60036020526000908152604090205481565b3480156103c657600080fd5b506103da6103d5366004614a13565b611136565b6040516101509190614f7e565b3480156103f357600080fd5b5061012e610402366004614d5b565b6111b6565b6104108161146b565b600081815260066020526040902060048101546001600160a01b031633148061045e575061045e7f3c98683c4fc1f07b3a173ce23e8e5b9ee147da7d8df6f5e0da4c07c15e354a0733611491565b61047b57604051630363e30760e61b815260040160405180910390fd5b600581015415806104a1575061048f611538565b816005015461049e9190614fa7565b42115b156104bf576040516360387b3360e01b815260040160405180910390fd5b6000828152600660205260408082206005018290555183917f7e98ef42b90939b396b85416fa66b14f7a5c284f7a7e794d995b3fad3c6e85cb91a25050565b6105277f3a2f5529773e03d975be44bdae98a8509bdf1159e407504e558536cde56cf6ac6115e5565b6001600160a01b0316336001600160a01b0316146105585760405163158a2f6b60e01b815260040160405180910390fd5b6105658585858585611672565b5050505050565b6105758161146b565b6000818152600660205260409020600581015415806105aa5750610597611538565b81600501546105a69190614fa7565b4211155b156105c857604051633527c42560e01b815260040160405180910390fd5b6000600582018190556002820154905b81811015610787578260030181815481106105f5576105f5614fba565b90600052602060002090602091828204019190069054906101000a900460ff1615610719576106437f494dfdc880823954ed6700117eb435b9bca3643417437b5781c1a89fba6e8b976115e5565b60048401546001850180546001600160a01b03938416936310d7d359931691908590811061067357610673614fba565b6000918252602090912001546002870180546001600160a01b0390921691869081106106a1576106a1614fba565b6000918252602090912001546040516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b1580156106fc57600080fd5b505af1158015610710573d6000803e3d6000fd5b5050505061077f565b600483015460028401805461077f926001600160a01b031691908490811061074357610743614fba565b906000526020600020015485600101848154811061076357610763614fba565b6000918252602090912001546001600160a01b03169190611a12565b6001016105d8565b506000838152600660205260408120906107a182826147ee565b6107af6001830160006147ee565b6107bd6002830160006147ee565b6107cb60038301600061480c565b506004810180546001600160a01b03191690556000600590910181905560405184917f4dcd0d064503785f7194bc0d094f808cd1df65b1440424e51cd211c9672f77cc91a2505050565b6001602052600090815260409020805461082e90614fd0565b80601f016020809104026020016040519081016040528092919081815260200182805461085a90614fd0565b80156108a75780601f1061087c576101008083540402835291602001916108a7565b820191906000526020600020905b81548152906001019060200180831161088a57829003601f168201915b505050505081565b6108d87f67ae681a1ce853cc4fa2ec7bd45049225042d6a828b9865aca9ef1218a52bcfc611a71565b6108e18361146b565b60008060008060006108f288611aa0565b985050509650505094509450945061092e8560018081111561091657610916614e4b565b60008b81526004602052604090205460ff1685611bdd565b61093b8482898986611c7d565b935061094b888486886001611db5565b60405188907f144d814d5dc6f17c1a88bc42c55d67392a51c818908ed7cca6118bc51a34b15390600090a25050505050505050565b6109a97f67ae681a1ce853cc4fa2ec7bd45049225042d6a828b9865aca9ef1218a52bcfc611a71565b6109b28561146b565b6000806000806109c189611aa0565b505050955050509350935093506109fd84600060018111156109e5576109e5614e4b565b60008c81526004602052604090205460ff1684611bdd565b600060ff821615610a2057610a168a8589898d8d611e79565b9094509050610a72565b610a6c8a8589896000818110610a3857610a38614fba565b905060200201358c8c6000818110610a5257610a52614fba565b9050602002016020810190610a67919061500a565b6123e6565b90945090505b610a7f8a84868885611db5565b6002816002811115610a9357610a93614e4b565b03610aef576040518a907fbce0bd6fef1367dca0b65255a7d010501f79e4dd96d4add4c3e42a419ae6457c90600090a26040518a907f21c4f33a94342256a428d6cb08476047bdb16e6866308b7d904df8990eb781c890600090a25b50505050505050505050565b610b247ff7c2c1de3464c8fee0ad8a71a80d665aeafd6a725243593923472fe5e76e45b1611a71565b610b2d8161146b565b600260008281526004602052604090205460ff166002811115610b5257610b52614e4b565b03610b7057604051635b114e0560e01b815260040160405180910390fd5b6000818152600460205260408120805460ff19811660021790915560ff1690808080808080610b9e89611aa0565b985098505097509750975050965096506000604051806040016040528089815260200188815250905060016002811115610bda57610bda614e4b565b8560ff161480610bed575060028560ff16145b15610d14576000610c1d7fba0b74768b1de73590a53e1384870dcbc846e5c73bab23c07d71eaa7cbf8411b6115e5565b90508460ff16600114610c9e576040516333e3072160e01b81526001600160a01b038216906333e3072190610c56908590600401615027565b6020604051808303816000875af1158015610c75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c999190615057565b610d0d565b6040516349e5b64960e01b81526001600160a01b038216906349e5b64990610cca908590600401615027565b6020604051808303816000875af1158015610ce9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0d9190615057565b5050610de8565b60ff8516610dcf57606060001960ff881601610d59578460ff16600114610d4657610d418b8986866124a6565b610d52565b610d528b8986866125cd565b9050610dbe565b60ff8716610dbe5760018a6002811115610d7557610d75614e4b565b14610d93576040516386f8e37560e01b815260040160405180910390fd5b8460ff16600114610daf57610daa8b8986866128fe565b610dbb565b610dbb8b898686612b55565b90505b610dc98b84836130ab565b50610de8565b60405163641c695560e01b815260040160405180910390fd5b6040518a907fbce0bd6fef1367dca0b65255a7d010501f79e4dd96d4add4c3e42a419ae6457c90600090a250505050505050505050565b6000333014610e41576040516332b3785760e11b815260040160405180910390fd5b610e4c8484846131dc565b90505b9392505050565b6040516302e2825b60e51b81523360048201527f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b031690635c504b6090602401602060405180830381865afa158015610eba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ede9190615084565b610efa576040516270dbdf60e11b815260040160405180910390fd5b600081806020019051810190610f1091906150e4565b9050806020015151602003610f8b5760008160200151806020019051810190610f39919061515a565b6000818152600360205260408120805492935091610f5690615173565b9091555060405181907ffeea67837572d96738a25f3ac5fa382a1c601ead52e97fb27a02c6103360c06390600090a250505050565b6000808154610f9990615173565b90915550805160008054815260026020908152604090912091909155808201518051610fcb929082018101910161518c565b60008054815260056020908152604080832060019092528220909190610ff18482615296565b5050825161100491906020850190614831565b5050506000547f0000000000000000000000000000000000000000000000000000000000013e316001600160401b0316846001600160401b03167f3371afb211a5a616ecaaab76f9466c9295fae2aa4e6dc1ed821b6eb25ee442cf60405160405180910390a45b505050565b60008181526006602090815260408083208054825181850281018501909352808352606094859490939183918301828280156110cb57602002820191906000526020600020905b8154815260200190600101908083116110b7575b505050505093508060020180548060200260200160405190810160405280929190818152602001828054801561112057602002820191906000526020600020905b81548152602001906001019080831161110c575b5050505050925080600501549150509193909250565b6000818152600560209081526040918290208054835181840281018401909452808452606093928301828280156111aa57602002820191906000526020600020906000905b825461010083900a900460ff1681526020600192830181810494850194909303909202910180841161117b5790505b50505050509050919050565b6111df7ff98729ec1ce0343ca1d11c51d1d2d3aa1a7b3f4f6876d0611e0a6fa86520a0cb611a71565b6111e88361146b565b600083815260066020526040902080541580611205575080548214155b15611223576040516344e945a960e01b815260040160405180910390fd5b6005810154156112455760405162aa3fd760e11b815260040160405180910390fd5b60008481526006602052604090206112619060020184846148d7565b50600084815260066020908152604080832042600590910155600290915281205460101c9060ff821660010361134757600086815260016020526040902080546112aa90614fd0565b80601f01602080910402602001604051908101604052809291908181526020018280546112d690614fd0565b80156113235780601f106112f857610100808354040283529160200191611323565b820191906000526020600020905b81548152906001019060200180831161130657829003601f168201915b505050505080602001905181019061133b9190615567565b610100015190506113f9565b6000868152600160205260409020805461136090614fd0565b80601f016020809104026020016040519081016040528092919081815260200182805461138c90614fd0565b80156113d95780601f106113ae576101008083540402835291602001916113d9565b820191906000526020600020905b8154815290600101906020018083116113bc57829003601f168201915b50505050508060200190518101906113f191906156f0565b610100015190505b6000868152600660205260409081902060040180546001600160a01b0319166001600160a01b0384161790555186907f78f133e107c1f55f0cb4abf0d9d0afc7d4949197a40bb9c88b97d51aec80f5cf9061145b9086908990899042906157b6565b60405180910390a2505050505050565b60005481111561148e576040516355da2ca360e11b815260040160405180910390fd5b50565b60006114bc7f6b50fa17b77d24e42e27a04b69fe50cd6967cfb767d18de0bd5fe7e1a32aa8686115e5565b604051632474521560e21b8152600481018590526001600160a01b03848116602483015291909116906391d1485490604401602060405180830381865afa15801561150b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061152f9190615084565b90505b92915050565b6000807f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316636a42b8f86040518163ffffffff1660e01b8152600401602060405180830381865afa158015611599573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115bd919061515a565b9050806000036115e05760405163d0b3066f60e01b815260040160405180910390fd5b919050565b6040516321f8a72160e01b8152600481018290526000907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a721906024015b602060405180830381865afa15801561164e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611532919061583d565b60008280602001905181019061168891906150e4565b855190915060008190036116af576040516324cb170560e01b815260040160405180910390fd5b6116b885613241565b6116c360018361585a565b10156116e257604051635b6b08d760e01b815260040160405180910390fd5b6000838060200190518101906116f8919061586d565b905061171d8760008151811061171057611710614fba565b60200260200101516132d5565b6001600160a01b0316639783d0ef826000015160008151811061174257611742614fba565b60200260200101518a896040518060400160405280896000015181526020018d8a6020015160405160200161177892919061596f565b60408051601f198184030181529181529152516117989190602001615027565b60405160208183030381529060405286602001516000815181106117be576117be614fba565b60200260200101516040518663ffffffff1660e01b81526004016117e59493929190615994565b6000604051808303818588803b1580156117fe57600080fd5b505af1158015611812573d6000803e3d6000fd5b50505050506001821115611a0857611829856132e0565b602084015260015b828160ff161015611a06578760008151811061184f5761184f614fba565b602002602001015160ff16888260ff168151811061186f5761186f614fba565b602002602001015160ff16036118985760405163182d291160e11b815260040160405180910390fd5b6118a36001826159e4565b60ff16158015906118fc5750876118bb6001836159e4565b60ff16815181106118ce576118ce614fba565b602002602001015160ff16888260ff16815181106118ee576118ee614fba565b602002602001015160ff1611155b1561191a576040516322aa062d60e01b815260040160405180910390fd5b611932888260ff168151811061171057611710614fba565b6001600160a01b0316639783d0ef83600001518360ff168151811061195957611959614fba565b60200260200101518b8a886040516020016119749190615027565b60405160208183030381529060405287602001518760ff168151811061199c5761199c614fba565b60200260200101516040518663ffffffff1660e01b81526004016119c39493929190615994565b6000604051808303818588803b1580156119dc57600080fd5b505af11580156119f0573d6000803e3d6000fd5b5050505050806119ff906159fd565b9050611831565b505b5050505050505050565b6040516001600160a01b0383811660248301526044820183905261106b91859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050613312565b611a7b8133611491565b61148e576040516361381e6b60e11b8152600481018290526024015b60405180910390fd5b6000818152600260209081526040808320546001909252822080549192606092909182918291829182918291829190611ad890614fd0565b80601f0160208091040260200160405190810160405280929190818152602001828054611b0490614fd0565b8015611b515780601f10611b2657610100808354040283529160200191611b51565b820191906000526020600020905b815481529060010190602001808311611b3457829003601f168201915b50505050509750611b7560405180604001604052808b81526020018a815250613375565b96508895505050600884901c92505050601082901c601883901c602084901c60c085901c611ba281613241565b6000888152600360205260409020541015611bd057604051635b6b08d760e01b815260040160405180910390fd5b9193959799909294969850565b60ff80851690600886901c811690601087901c90861683148015611bff575081155b611c1c576040516330be21b360e11b815260040160405180910390fd5b6000856002811115611c3057611c30614e4b565b14611c4e576040516353b4315360e11b815260040160405180910390fd5b8360ff168160ff1614611c74576040516330be21b360e11b815260040160405180910390fd5b50505050505050565b6060611c87614912565b611c8f61496e565b8360ff16600103611cb55787806020019051810190611cae9190615567565b9150611cd7565b87806020019051810190611cc991906156f0565b9050611cd4816133a5565b91505b60a0820151518514611cfc5760405163707ea55960e11b815260040160405180910390fd5b611d298686848a7f0000000000000000000000000000000000000000000000000000000000013e3161359f565b91508360ff16600003611d87578160a00151600081518110611d4d57611d4d614fba565b6020908102919091018101515160a083015152604051611d6f91839101615b28565b60405160208183030381529060405292505050611dac565b81604051602001611d989190615bc8565b604051602081830303815290604052925050505b95945050505050565b6000611dd4604051806040016040528085815260200186815250613375565b9050848114611dfd57600085815260036020526040808220805484845291832091909155868252555b6000868152600160205260409020611e158582615296565b506000868152600460205260409020805483919060ff19166001836002811115611e4157611e41614e4b565b021790555060405186907f144d814d5dc6f17c1a88bc42c55d67392a51c818908ed7cca6118bc51a34b15390600090a2505050505050565b606060008087806020019051810190611e929190615567565b60408101515190915086908114611ebc57604051637753355f60e11b815260040160405180910390fd5b6000805b8281101561201d57898982818110611eda57611eda614fba565b90506020020135600003611f0157604051630f6fa54560e41b815260040160405180910390fd5b611fed611f2d7f494dfdc880823954ed6700117eb435b9bca3643417437b5781c1a89fba6e8b976115e5565b8560c001518381518110611f4357611f43614fba565b60200260200101518e848e8e87818110611f5f57611f5f614fba565b905060200201358d8d88818110611f7857611f78614fba565b9050602002016020810190611f8d919061500a565b8a602001518881518110611fa357611fa3614fba565b60200260200101518b604001518981518110611fc157611fc1614fba565b60200260200101518c608001518a81518110611fdf57611fdf614fba565b60200260200101518b613ae9565b90508560400151838151811061200557612005614fba565b60209081029190910101919091529150600101611ec0565b5080156123b1576000816001600160401b0381111561203e5761203e614a41565b604051908082528060200260200182016040528015612067578160200160208202803683370190505b5090506000826001600160401b0381111561208457612084614a41565b6040519080825280602002602001820160405280156120ad578160200160208202803683370190505b5090506000836001600160401b038111156120ca576120ca614a41565b6040519080825280602002602001820160405280156120f3578160200160208202803683370190505b5090506000846001600160401b0381111561211057612110614a41565b604051908082528060200260200182016040528015612139578160200160208202803683370190505b5090506000856001600160401b0381111561215657612156614a41565b60405190808252806020026020018201604052801561217f578160200160208202803683370190505b5090506000866001600160401b0381111561219c5761219c614a41565b6040519080825280602002602001820160405280156121c5578160200160208202803683370190505b5090506000805b8981101561237f578a6040015181815181106121ea576121ea614fba565b6020026020010151600014612377578a60200151818151811061220f5761220f614fba565b602002602001015188838151811061222957612229614fba565b6020026020010181815250508a60400151818151811061224b5761224b614fba565b602002602001015187838151811061226557612265614fba565b6020026020010181815250508a60600151818151811061228757612287614fba565b60200260200101518683815181106122a1576122a1614fba565b6020026020010181815250508a6080015181815181106122c3576122c3614fba565b60200260200101518583815181106122dd576122dd614fba565b6020026020010181815250508a60c0015181815181106122ff576122ff614fba565b602002602001015184838151811061231957612319614fba565b6020026020010190151590811515815250508a60e00151818151811061234157612341614fba565b602002602001015183838151811061235b5761235b614fba565b9115156020928302919091019091015261237482615173565b91505b6001016121cc565b5050602089019590955260408801939093526060870191909152608086015260c085015260e0840152600193506123b6565b600293505b826040516020016123c79190615bc8565b6040516020818303038152906040529450505050965096945050505050565b6060600080858060200190518101906123ff91906156f0565b90508460000361242257604051630f6fa54560e41b815260040160405180910390fd5b61246e61244e7f494dfdc880823954ed6700117eb435b9bca3643417437b5781c1a89fba6e8b976115e5565b8260c0015189600089898760200151886040015189608001516000613ae9565b50604080840192909252905190925061248b908290602001615b28565b60405160208183030381529060405292505094509492505050565b60606000848060200190518101906124be91906156f0565b6040805160208082018a905260008284015282518083038401815260609092019092526101208301528101519091506124f690613e80565b6125135760405163a412f06560e01b815260040160405180910390fd5b6125208160200151613f19565b6001600160a01b031663ef164fef8286866040518463ffffffff1660e01b815260040161254f93929190615cdb565b6020604051808303816000875af192505050801561258a575060408051601f3d908101601f191682019092526125879181019061515a565b60015b6125b2576125aa8482600001516001600285602001518660400151613f2d565b9150506125c5565b5050506040805160208101909152600081525b949350505050565b60606000848060200190518101906125e59190615567565b6020810151519091506000908161261b7fbcc180fb907e9ae431665de4bc74305c00b7b27442aadd477980ecc4bb14c0116115e5565b905060005b828110156128b457816001600160a01b031663b5c756978660200151838151811061264d5761264d614fba565b60200260200101516040518263ffffffff1660e01b815260040161267391815260200190565b602060405180830381865afa158015612690573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b49190615084565b6126d15760405163a412f06560e01b815260040160405180910390fd5b6126f7856020015182815181106126ea576126ea614fba565b6020026020010151613f19565b6001600160a01b031663ef164fef604051806101400160405280886000015181526020018860200151858151811061273157612731614fba565b602002602001015181526020018860400151858151811061275457612754614fba565b602002602001015181526020018860600151858151811061277757612777614fba565b602002602001015181526020018860800151858151811061279a5761279a614fba565b602002602001015181526020018860a0015185815181106127bd576127bd614fba565b602002602001015181526020016000151581526020016000151581526020018861010001516001600160a01b031681526020018d8560405160200161280c929190918252602082015260400190565b6040516020818303038152906040528152508a8a6040518463ffffffff1660e01b815260040161283e93929190615cdb565b6020604051808303816000875af1925050508015612879575060408051601f3d908101601f191682019092526128769181019061515a565b60015b61288657600193506128ac565b5060008560400151828151811061289f5761289f614fba565b6020026020010181815250505b600101612620565b5082156128e2576128d7878560000151600160028860200151896040015161405d565b9450505050506125c5565b5050604080516020810190915260008152979650505050505050565b606060008480602001905181019061291691906156f0565b905060006129278260200151613f19565b90506000612934826140cc565b60408481015190516370a0823160e01b815230600482015291925082916001600160a01b038316906370a0823190602401602060405180830381865afa158015612982573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129a6919061515a565b10612b3c5760408401516129c6906001600160a01b03831690859061410c565b604051634af278ed60e11b81526001600160a01b038416906395e4f1da906129f69087908b908b90600401615cdb565b6020604051808303816000875af1925050508015612a31575060408051601f3d908101601f19168201909252612a2e9181019061515a565b60015b612afc576040840151612a50906001600160a01b03831690859061419c565b60008981526006602090815260408083208783015181546001808201845583875285872090910191909155808201805480830182559086528486200180546001600160a01b0319166001600160a01b03891617905560039091018054918201815584528284209281049092018054601f9093166101000a60ff0219909216909155518a917f21c4f33a94342256a428d6cb08476047bdb16e6866308b7d904df8990eb781c891a26128e2565b8015801590612b0d57508460e00151155b15612b3657612b2a88866000015160006001896020015186613f2d565b955050505050506125c5565b506128e2565b604051630399226960e41b815260040160405180910390fd5b6060600084806020019051810190612b6d9190615567565b90506000612b7e8260200151614259565b6020830151519091506000908180805b8381101561302b5786604001518181518110612bac57612bac614fba565b602002602001015160001461302357612bdd868281518110612bd057612bd0614fba565b60200260200101516140cc565b945086604001518181518110612bf557612bf5614fba565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa158015612c44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c68919061515a565b10612b3c57612cc1868281518110612c8257612c82614fba565b602002602001015188604001518381518110612ca057612ca0614fba565b6020026020010151876001600160a01b031661410c9092919063ffffffff16565b612cc96149c9565b868281518110612cdb57612cdb614fba565b60200260200101516001600160a01b03166395e4f1da6040518061014001604052808b6000015181526020018b602001518681518110612d1d57612d1d614fba565b602002602001015181526020018b604001518681518110612d4057612d40614fba565b602002602001015181526020018b606001518681518110612d6357612d63614fba565b602002602001015181526020018b608001518681518110612d8657612d86614fba565b602002602001015181526020018481526020016000151581526020018b60e001518681518110612db857612db8614fba565b6020026020010151151581526020018b61010001516001600160a01b031681526020018b61012001518152508d8d6040518463ffffffff1660e01b8152600401612e0493929190615cdb565b6020604051808303816000875af1925050508015612e3f575060408051601f3d908101601f19168201909252612e3c9181019061515a565b60015b612f9f57612e97878381518110612e5857612e58614fba565b602002602001015189604001518481518110612e7657612e76614fba565b6020026020010151886001600160a01b031661419c9092919063ffffffff16565b60008d81526006602090815260409091209089015180516001955084908110612ec257612ec2614fba565b60209081029190910181015182546001810184556000938452918320909101556040890151805184908110612ef957612ef9614fba565b602002602001018181525050600660008e8152602001908152602001600020600101612f30888481518110612bd057612bd0614fba565b8154600180820184556000938452602080852090920180546001600160a01b0319166001600160a01b0394909416939093179092558f83526006815260408320600301805492830181558352918290209181049091018054601f9092166101000a60ff02199091169055613021565b8015801590612fc957508860e001518381518110612fbf57612fbf614fba565b6020026020010151155b15612ffa57600194508089604001518481518110612fe957612fe9614fba565b60200260200101818152505061301f565b60008960400151848151811061301257613012614fba565b6020026020010181815250505b505b505b600101612b8e565b50801561305e576040518b907f21c4f33a94342256a428d6cb08476047bdb16e6866308b7d904df8990eb781c890600090a25b811561308d57613080898760000151600060018a602001518b6040015161405d565b96505050505050506125c5565b50506040805160208101909152600081529998505050505050505050565b80511561106b5760008381526005602090815260408083208054825181850281018501909352808352919290919083018282801561312657602002820191906000526020600020906000905b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116130f75790505b5050505050905060006131587fab437a16135e856111e538dc45051dd9c2778c6069d25a22fb9ac4766c356aa16115e5565b6001600160a01b0316633283166a8584866040518463ffffffff1660e01b815260040161318793929190615d17565b600060405180830381865afa1580156131a4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526131cc9190810190615d4b565b9150506105653383868685611672565b6000828411156131ff5760405163c8a403d160e01b815260040160405180910390fd5b600061271061320e848261585a565b6132189086615d87565b6132229190615d9e565b905080851015613236576000915050610e4f565b506001949350505050565b604051631049a0db60e01b81526001600160401b03821660048201526000907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b031690631049a0db90602401602060405180830381865afa1580156132b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611532919061515a565b60006115328261430b565b606081805190602001206040516020016132fc91815260200190565b6040516020818303038152906040529050919050565b60006133276001600160a01b0384168361435d565b9050805160001415801561334c57508080602001905181019061334a9190615084565b155b1561106b57604051635274afe760e01b81526001600160a01b0384166004820152602401611a97565b6000816040516020016133889190615027565b604051602081830303815290604052805190602001209050919050565b6133ad614912565b604080516001808252818301909252600091602080830190803683370190505090508260200151816000815181106133e7576133e7614fba565b602090810291909101015260408051600180825281830190925260009181602001602082028036833701905050905083604001518160008151811061342e5761342e614fba565b602090810291909101015260408051600180825281830190925260009181602001602082028036833701905050905084606001518160008151811061347557613475614fba565b60209081029190910101526040805160018082528183019092526000918160200160208202803683370190505090508560800151816000815181106134bc576134bc614fba565b6020908102919091010152604080516001808252818301909252600091816020015b6134e66149c9565b8152602001906001900390816134de5790505090508660a001518160008151811061351357613513614fba565b60200260200101819052506040518061014001604052808860000151815260200186815260200185815260200184815260200183815260200182815260200161355f8960c0015161436b565b81526020016135718960e0015161436b565b81526020018861010001516001600160a01b0316815260200188610120015181525095505050505050919050565b6135a7614912565b60a0840151516000805b82811015613adc578888828181106135cb576135cb614fba565b90506020028101906135dd9190615dc0565b158015915061360e57508660a0015181815181106135fd576135fd614fba565b602002602001015160000151516000145b15613ad45761362c876020015182815181106126ea576126ea614fba565b9150613637306143b6565b60ff16826001600160a01b03166391deb8826040518163ffffffff1660e01b8152600401602060405180830381865afa158015613678573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061369c9190615e06565b60ff1603613ad4576136ca8760a0015182815181106136bd576136bd614fba565b6020026020010151614445565b60007f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b031663e85b2b548960a00151848151811061371157613711614fba565b6020026020010151606001516040518263ffffffff1660e01b8152600401613742919060ff91909116815260200190565b602060405180830381865afa15801561375f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613783919061583d565b9050806001600160a01b031663c87439eb6040518061012001604052808d8d878181106137b2576137b2614fba565b90506020028101906137c49190615dc0565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506001600160401b03808b1660208301528b16604082015260a08c015180516060909201918790811061382f5761382f614fba565b6020026020010151608001516001600160401b03168152602001600015158152602001866001600160a01b031681526020018b61010001516001600160a01b0316815260200161387e876140cc565b6001600160a01b0316815260006020909101526040516001600160e01b031960e084901b1681526138b29190600401615e23565b602060405180830381865afa1580156138cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f39190615084565b50613a3a816001600160a01b0316639bbbb5c88c8c8681811061391857613918614fba565b905060200281019061392a9190615dc0565b60006040518463ffffffff1660e01b815260040161394a93929190615ef6565b602060405180830381865afa158015613967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061398b919061515a565b846001600160a01b031663b7ba28cd8b6040015186815181106139b0576139b0614fba565b60200260200101516040518263ffffffff1660e01b81526004016139d691815260200190565b602060405180830381865afa1580156139f3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a17919061515a565b8a608001518581518110613a2d57613a2d614fba565b60200260200101516131dc565b613a57576040516358d0562960e11b815260040160405180910390fd5b898983818110613a6957613a69614fba565b9050602002810190613a7b9190615dc0565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050505060a0890151805184908110613ac657613ac6614fba565b602090810291909101015152505b6001016135b1565b5094979650505050505050565b600080806001600160a01b038816613b14576040516331b5a77960e11b815260040160405180910390fd5b60008c15613cf757898e6001600160a01b031663c830c85a8e8e6040518363ffffffff1660e01b8152600401613b54929190918252602082015260400190565b602060405180830381865afa158015613b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b95919061515a565b14613cf7576000808f6001600160a01b03166395c2c5d78f8f6040518363ffffffff1660e01b8152600401613bd4929190918252602082015260400190565b6040805180830381865afa158015613bf0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c149190615f2e565b915091508b8114613c38576040516320590e3d60e11b815260040160405180910390fd5b8a6001600160a01b0316826001600160a01b031614613c6a576040516325bfc2e360e11b815260040160405180910390fd5b5060008d815260066020908152604082208054600181810183558285528385209091018d9055818101805480830182559085528385200180546001600160a01b039096166001600160a01b03199096169590951790945560030180548085018255908352818320918104909101805460ff601f9093166101000a9283021916909117905597506002935090505b80613e6b5760405163803c15df60e01b8152600481018b90526024810188905260448101879052309063803c15df90606401602060405180830381865afa925050508015613d62575060408051601f3d908101601f19168201909252613d5f91810190615084565b60015b613d6f5760019250613d7f565b8015613d7d578a9750600193505b505b613d8888613e80565b8015613da557506001836002811115613da357613da3614e4b565b145b613e525760008c815260066020908152604082208054600181810183559184529183209091018a9055613ddb908a908c9061447e565b60008e815260066020908152604082206001808201805480830182559085528385200180546001600160a01b0319166001600160a01b039690961695909517909455600301805493840181558252808220908304018054601f9093166101000a60ff0219909216909155975060029350613e6b9050565b613e5e888a600061447e565b50613e6885615173565b94505b50949c909b5091995090975050505050505050565b6000613eab7fbcc180fb907e9ae431665de4bc74305c00b7b27442aadd477980ecc4bb14c0116115e5565b6001600160a01b031663b5c75697836040518263ffffffff1660e01b8152600401613ed891815260200190565b602060405180830381865afa158015613ef5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115329190615084565b6000613f2482614565565b50909392505050565b60606040518060400160405280613fe6876001811115613f4f57613f4f614e4b565b876002811115613f6157613f61614e4b565b6000613f6c306143b6565b8d7f0000000000000000000000000000000000000000000000000000000000013e3160ff9590951660089490941b61ff00169390931760109290921b62ff0000169190911760189190911b63ff000000161760209190911b640100000000600160c01b03161760c09190911b6001600160c01b0319161790565b815260408051606080820183528a8252602082810189815292840188815284518083018e90529351948401949094529251908201529101906080015b60408051601f198184030181529181529152516140429190602001615027565b60405160208183030381529060405290509695505050505050565b6060604051806040016040528061409c87600181111561407f5761407f614e4b565b87600281111561409157614091614e4b565b6001613f6c306143b6565b81526020016040518060600160405280898152602001868152602001858152506040516020016140229190615f5c565b6000816001600160a01b031663b60262ca6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561164e573d6000803e3d6000fd5b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa15801561415c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614180919061515a565b905061419684846141918585614fa7565b614599565b50505050565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa1580156141ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614210919061515a565b90508181101561424c5760405163e570110f60e01b81526001600160a01b03841660048201526024810182905260448101839052606401611a97565b6141968484848403614599565b8051606090806001600160401b0381111561427657614276614a41565b60405190808252806020026020018201604052801561429f578160200160208202803683370190505b50915060005b81811015614304576142cf8482815181106142c2576142c2614fba565b6020026020010151614565565b9050508382815181106142e4576142e4614fba565b6001600160a01b03909216602092830291909101909101526001016142a5565b5050919050565b604051630eff125d60e01b815260ff821660048201526000907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b031690630eff125d90602401611631565b606061152f83836000614629565b6040805160018082528183019092526060916020808301908036833701905050905081816000815181106143a1576143a1614fba565b91151560209283029190910190910152919050565b604051632f6438ab60e01b81526001600160a01b0382811660048301526000917f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a251490911690632f6438ab90602401602060405180830381865afa158015614421573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115329190615e06565b60208101516001600160a01b03161580614460575080515115155b1561148e57604051630c57767d60e41b815260040160405180910390fd5b600061448984613f19565b6001600160a01b031663b60262ca6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156144e2575060408051601f3d908101601f191682019092526144df9181019061583d565b60015b15614527578280156145065750836001600160a01b0316816001600160a01b031614155b15614524576040516325bfc2e360e11b815260040160405180910390fd5b90505b811580156145475750826001600160a01b0316816001600160a01b031614155b15610e4f576040516325bfc2e360e11b815260040160405180910390fd5b8060a081901c60c082901c60008190036145925760405163030042b760e01b815260040160405180910390fd5b9193909250565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b1790526145ea84826146c6565b614196576040516001600160a01b0384811660248301526000604483015261461f91869182169063095ea7b390606401611a3f565b6141968482613312565b60608147101561464e5760405163cd78605960e01b8152306004820152602401611a97565b600080856001600160a01b0316848660405161466a9190615f9f565b60006040518083038185875af1925050503d80600081146146a7576040519150601f19603f3d011682016040523d82523d6000602084013e6146ac565b606091505b50915091506146bc868383614769565b9695505050505050565b6000806000846001600160a01b0316846040516146e39190615f9f565b6000604051808303816000865af19150503d8060008114614720576040519150601f19603f3d011682016040523d82523d6000602084013e614725565b606091505b509150915081801561474f57508051158061474f57508080602001905181019061474f9190615084565b8015611dac5750505050506001600160a01b03163b151590565b60608261477e57614779826147c5565b610e4f565b815115801561479557506001600160a01b0384163b155b156147be57604051639996b31560e01b81526001600160a01b0385166004820152602401611a97565b5080610e4f565b8051156147d55780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b508054600082559060005260206000209081019061148e91906149fe565b50805460008255601f01602090049060005260206000209081019061148e91906149fe565b82805482825590600052602060002090601f016020900481019282156148c75791602002820160005b8382111561489857835183826101000a81548160ff021916908360ff160217905550926020019260010160208160000104928301926001030261485a565b80156148c55782816101000a81549060ff0219169055600101602081600001049283019260010302614898565b505b506148d39291506149fe565b5090565b8280548282559060005260206000209081019282156148c7579160200282015b828111156148c75782358255916020019190600101906148f7565b604051806101400160405280600081526020016060815260200160608152602001606081526020016060815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001606081525090565b60405180610140016040528060008152602001600081526020016000815260200160008152602001600081526020016149a56149c9565b81526000602082018190526040820181905260608083019190915260809091015290565b6040805160c081018252606080825260006020830181905292820183905281018290526080810182905260a081019190915290565b5b808211156148d357600081556001016149ff565b600060208284031215614a2557600080fd5b5035919050565b6001600160a01b038116811461148e57600080fd5b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715614a7957614a79614a41565b60405290565b60405161014081016001600160401b0381118282101715614a7957614a79614a41565b604051601f8201601f191681016001600160401b0381118282101715614aca57614aca614a41565b604052919050565b60006001600160401b03821115614aeb57614aeb614a41565b5060051b60200190565b60ff8116811461148e57600080fd5b6001600160401b038116811461148e57600080fd5b80356115e081614b04565b60006001600160401b03821115614b3d57614b3d614a41565b50601f01601f191660200190565b600082601f830112614b5c57600080fd5b8135614b6f614b6a82614b24565b614aa2565b818152846020838601011115614b8457600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a08688031215614bb957600080fd5b8535614bc481614a2c565b94506020868101356001600160401b0380821115614be157600080fd5b818901915089601f830112614bf557600080fd5b8135614c03614b6a82614ad2565b81815260059190911b8301840190848101908c831115614c2257600080fd5b938501935b82851015614c49578435614c3a81614af5565b82529385019390850190614c27565b9850614c5a91505060408a01614b19565b95506060890135925080831115614c7057600080fd5b614c7c8a848b01614b4b565b94506080890135925080831115614c9257600080fd5b5050614ca088828901614b4b565b9150509295509295909350565b60005b83811015614cc8578181015183820152602001614cb0565b50506000910152565b60008151808452614ce9816020860160208601614cad565b601f01601f19169290920160200192915050565b60208152600061152f6020830184614cd1565b60008083601f840112614d2257600080fd5b5081356001600160401b03811115614d3957600080fd5b6020830191508360208260051b8501011115614d5457600080fd5b9250929050565b600080600060408486031215614d7057600080fd5b8335925060208401356001600160401b03811115614d8d57600080fd5b614d9986828701614d10565b9497909650939450505050565b600080600080600060608688031215614dbe57600080fd5b8535945060208601356001600160401b0380821115614ddc57600080fd5b614de889838a01614d10565b90965094506040880135915080821115614e0157600080fd5b50614e0e88828901614d10565b969995985093965092949392505050565b600080600060608486031215614e3457600080fd5b505081359360208301359350604090920135919050565b634e487b7160e01b600052602160045260246000fd5b6020810160038310614e8357634e487b7160e01b600052602160045260246000fd5b91905290565b60008060408385031215614e9c57600080fd5b8235614ea781614b04565b915060208301356001600160401b03811115614ec257600080fd5b614ece85828601614b4b565b9150509250929050565b60008151808452602080850194506020840160005b83811015614f0957815187529582019590820190600101614eed565b509495945050505050565b606081526000614f276060830186614ed8565b8281036020840152614f398186614ed8565b915050826040830152949350505050565b60008151808452602080850194506020840160005b83811015614f0957815160ff1687529582019590820190600101614f5f565b60208152600061152f6020830184614f4a565b634e487b7160e01b600052601160045260246000fd5b8082018082111561153257611532614f91565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680614fe457607f821691505b60208210810361500457634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561501c57600080fd5b8135610e4f81614a2c565b6020815281516020820152600060208301516040808401526125c56060840182614cd1565b80516115e081614b04565b60006020828403121561506957600080fd5b8151610e4f81614b04565b805180151581146115e057600080fd5b60006020828403121561509657600080fd5b61152f82615074565b600082601f8301126150b057600080fd5b81516150be614b6a82614b24565b8181528460208386010111156150d357600080fd5b6125c5826020830160208701614cad565b6000602082840312156150f657600080fd5b81516001600160401b038082111561510d57600080fd5b908301906040828603121561512157600080fd5b615129614a57565b8251815260208301518281111561513f57600080fd5b61514b8782860161509f565b60208301525095945050505050565b60006020828403121561516c57600080fd5b5051919050565b60006001820161518557615185614f91565b5060010190565b6000806040838503121561519f57600080fd5b82516001600160401b03808211156151b657600080fd5b818501915085601f8301126151ca57600080fd5b815160206151da614b6a83614ad2565b82815260059290921b840181019181810190898411156151f957600080fd5b948201945b8386101561522057855161521181614af5565b825294820194908201906151fe565b9188015191965090935050508082111561523957600080fd5b50614ece8582860161509f565b601f82111561106b576000816000526020600020601f850160051c8101602086101561526f5750805b601f850160051c820191505b8181101561528e5782815560010161527b565b505050505050565b81516001600160401b038111156152af576152af614a41565b6152c3816152bd8454614fd0565b84615246565b602080601f8311600181146152f857600084156152e05750858301515b600019600386901b1c1916600185901b17855561528e565b600085815260208120601f198616915b8281101561532757888601518255948401946001909101908401615308565b50858210156153455787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600082601f83011261536657600080fd5b81516020615376614b6a83614ad2565b8083825260208201915060208460051b87010193508684111561539857600080fd5b602086015b848110156153b4578051835291830191830161539d565b509695505050505050565b80516115e081614a2c565b600060c082840312156153dc57600080fd5b60405160c081016001600160401b0382821081831117156153ff576153ff614a41565b81604052829350845191508082111561541757600080fd5b506154248582860161509f565b825250602083015161543581614a2c565b6020820152604083015161544881614a2c565b6040820152606083015161545b81614af5565b606082015261546c6080840161504c565b608082015260a083015160a08201525092915050565b600082601f83011261549357600080fd5b815160206154a3614b6a83614ad2565b82815260059290921b840181019181810190868411156154c257600080fd5b8286015b848110156153b45780516001600160401b038111156154e55760008081fd5b6154f38986838b01016153ca565b8452509183019183016154c6565b600082601f83011261551257600080fd5b81516020615522614b6a83614ad2565b8083825260208201915060208460051b87010193508684111561554457600080fd5b602086015b848110156153b45761555a81615074565b8352918301918301615549565b60006020828403121561557957600080fd5b81516001600160401b038082111561559057600080fd5b9083019061014082860312156155a557600080fd5b6155ad614a7f565b825181526020830151828111156155c357600080fd5b6155cf87828601615355565b6020830152506040830151828111156155e757600080fd5b6155f387828601615355565b60408301525060608301518281111561560b57600080fd5b61561787828601615355565b60608301525060808301518281111561562f57600080fd5b61563b87828601615355565b60808301525060a08301518281111561565357600080fd5b61565f87828601615482565b60a08301525060c08301518281111561567757600080fd5b61568387828601615501565b60c08301525060e08301518281111561569b57600080fd5b6156a787828601615501565b60e0830152506101006156bb8185016153bf565b9082015261012083810151838111156156d357600080fd5b6156df8882870161509f565b918301919091525095945050505050565b60006020828403121561570257600080fd5b81516001600160401b038082111561571957600080fd5b90830190610140828603121561572e57600080fd5b615736614a7f565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a08301518281111561577457600080fd5b615780878286016153ca565b60a08301525061579260c08401615074565b60c08201526157a360e08401615074565b60e08201526101006156bb8185016153bf565b600060608201606083528087548083526080850191508860005260209250602060002060005b828110156157f8578154845292840192600191820191016157dc565b50505083810360208501528581526001600160fb1b0386111561581a57600080fd5b8560051b9150818760208301376040939093019390935250016020019392505050565b60006020828403121561584f57600080fd5b8151610e4f81614a2c565b8181038181111561153257611532614f91565b6000602080838503121561588057600080fd5b82516001600160401b038082111561589757600080fd5b90840190604082870312156158ab57600080fd5b6158b3614a57565b8251828111156158c257600080fd5b6158ce88828601615355565b82525083830151828111156158e257600080fd5b80840193505086601f8401126158f757600080fd5b8251615905614b6a82614ad2565b81815260059190911b8401850190858101908983111561592457600080fd5b8686015b8381101561595c578051868111156159405760008081fd5b61594e8c8a838b010161509f565b845250918701918701615928565b5095830195909552509695505050505050565b6040815260006159826040830185614f4a565b8281036020840152611dac8185614cd1565b6001600160a01b03851681526001600160401b03841660208201526080604082018190526000906159c790830185614cd1565b82810360608401526159d98185614cd1565b979650505050505050565b60ff828116828216039081111561153257611532614f91565b600060ff821660ff8103615a1357615a13614f91565b60010192915050565b6000815160c08452615a3160c0850182614cd1565b9050602083015160018060a01b038082166020870152806040860151166040870152505060ff60608401511660608501526001600160401b03608084015116608085015260a083015160a08501528091505092915050565b6000610140825184526020830151602085015260408301516040850152606083015160608501526080830151608085015260a08301518160a0860152615ad182860182615a1c565b91505060c0830151615ae760c086018215159052565b5060e0830151615afb60e086018215159052565b50610100838101516001600160a01b03169085015261012080840151858303828701526146bc8382614cd1565b60208152600061152f6020830184615a89565b60008282518085526020808601955060208260051b8401016020860160005b84811015615b8857601f19868403018952615b76838351615a1c565b98840198925090830190600101615b5a565b5090979650505050505050565b60008151808452602080850194506020840160005b83811015614f09578151151587529582019590820190600101615baa565b602081528151602082015260006020830151610140806040850152615bf1610160850183614ed8565b91506040850151601f1980868503016060870152615c0f8483614ed8565b93506060870151915080868503016080870152615c2c8483614ed8565b935060808701519150808685030160a0870152615c498483614ed8565b935060a08701519150808685030160c0870152615c668483615b3b565b935060c08701519150808685030160e0870152615c838483615b95565b935060e08701519150610100818786030181880152615ca28584615b95565b945080880151925050610120615cc2818801846001600160a01b03169052565b8701518685039091018387015290506146bc8382614cd1565b606081526000615cee6060830186615a89565b6001600160a01b03949094166020830152506001600160401b0391909116604090910152919050565b6001600160401b0384168152606060208201526000615d396060830185614f4a565b82810360408401526146bc8185614cd1565b60008060408385031215615d5e57600080fd5b8251915060208301516001600160401b03811115615d7b57600080fd5b614ece8582860161509f565b808202811582820484141761153257611532614f91565b600082615dbb57634e487b7160e01b600052601260045260246000fd5b500490565b6000808335601e19843603018112615dd757600080fd5b8301803591506001600160401b03821115615df157600080fd5b602001915036819003821315614d5457600080fd5b600060208284031215615e1857600080fd5b8151610e4f81614af5565b6020815260008251610120806020850152615e42610140850183614cd1565b91506020850151615e5e60408601826001600160401b03169052565b5060408501516001600160401b03811660608601525060608501516001600160401b038116608086015250608085015180151560a08601525060a08501516001600160a01b03811660c08601525060c08501516001600160a01b03811660e08601525060e0850151610100615edd818701836001600160a01b03169052565b909501516001600160a01b031693019290925250919050565b6040815282604082015282846060830137600060608483018101919091529115156020820152601f909201601f191690910101919050565b60008060408385031215615f4157600080fd5b8251615f4c81614a2c565b6020939093015192949293505050565b60208152815160208201526000602083015160606040840152615f826080840182614ed8565b90506040840151601f19848303016060850152611dac8282614ed8565b60008251615fb1818460208701614cad565b919091019291505056fea2646970667358221220374638a3255ecd4b127cbbc75e1971d2594ffd45b6f30f95ddae7ab6ec7214fd64736f6c63430008170033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.