Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Latest 25 from a total of 2,418 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Interchain Execu... | 6459427 | 34 days ago | IN | 0 ETH | 0.00620415 | ||||
Interchain Execu... | 6459370 | 34 days ago | IN | 0 ETH | 0.00503179 | ||||
Interchain Execu... | 6459365 | 34 days ago | IN | 0 ETH | 0.00578105 | ||||
Interchain Execu... | 6459315 | 34 days ago | IN | 0 ETH | 0.00575737 | ||||
Interchain Execu... | 6459311 | 34 days ago | IN | 0 ETH | 0.00530566 | ||||
Interchain Execu... | 6459237 | 34 days ago | IN | 0 ETH | 0.00169868 | ||||
Interchain Execu... | 6459214 | 34 days ago | IN | 0 ETH | 0.00216502 | ||||
Interchain Execu... | 6459214 | 34 days ago | IN | 0 ETH | 0.00208634 | ||||
Interchain Execu... | 6459214 | 34 days ago | IN | 0 ETH | 0.00208634 | ||||
Interchain Execu... | 6459157 | 34 days ago | IN | 0 ETH | 0.00181314 | ||||
Interchain Execu... | 6459123 | 34 days ago | IN | 0 ETH | 0.00096211 | ||||
Interchain Execu... | 6459088 | 34 days ago | IN | 0 ETH | 0.0015755 | ||||
Interchain Execu... | 6459088 | 34 days ago | IN | 0 ETH | 0.0015755 | ||||
Interchain Execu... | 6459064 | 34 days ago | IN | 0 ETH | 0.00206174 | ||||
Interchain Execu... | 6459033 | 34 days ago | IN | 0 ETH | 0.00161357 | ||||
Interchain Execu... | 6458978 | 34 days ago | IN | 0 ETH | 0.00186251 | ||||
Interchain Execu... | 6458978 | 34 days ago | IN | 0 ETH | 0.00186251 | ||||
Interchain Execu... | 6458953 | 34 days ago | IN | 0 ETH | 0.00192624 | ||||
Interchain Execu... | 6458924 | 34 days ago | IN | 0 ETH | 0.00111733 | ||||
Interchain Execu... | 6458893 | 34 days ago | IN | 0 ETH | 0.00043192 | ||||
Interchain Execu... | 6458893 | 34 days ago | IN | 0 ETH | 0.00043192 | ||||
Interchain Execu... | 6458844 | 34 days ago | IN | 0 ETH | 0.00088093 | ||||
Interchain Execu... | 6458841 | 34 days ago | IN | 0 ETH | 0.00083249 | ||||
Interchain Execu... | 6458784 | 34 days ago | IN | 0 ETH | 0.00091348 | ||||
Interchain Execu... | 6458784 | 34 days ago | IN | 0 ETH | 0.00091348 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
6589119 | 14 days ago | 0 ETH | ||||
6589119 | 14 days ago | 0 ETH | ||||
6589119 | 14 days ago | 0 ETH | ||||
6459427 | 34 days ago | 0 ETH | ||||
6459427 | 34 days ago | 0 ETH | ||||
6459427 | 34 days ago | 0 ETH | ||||
6459370 | 34 days ago | 0 ETH | ||||
6459370 | 34 days ago | 0 ETH | ||||
6459370 | 34 days ago | 0 ETH | ||||
6459365 | 34 days ago | 0 ETH | ||||
6459365 | 34 days ago | 0 ETH | ||||
6459365 | 34 days ago | 0 ETH | ||||
6459315 | 34 days ago | 0 ETH | ||||
6459315 | 34 days ago | 0 ETH | ||||
6459315 | 34 days ago | 0 ETH | ||||
6459311 | 34 days ago | 0 ETH | ||||
6459311 | 34 days ago | 0 ETH | ||||
6459311 | 34 days ago | 0 ETH | ||||
6459237 | 34 days ago | 0 ETH | ||||
6459237 | 34 days ago | 0 ETH | ||||
6459237 | 34 days ago | 0 ETH | ||||
6459214 | 34 days ago | 0 ETH | ||||
6459214 | 34 days ago | 0 ETH | ||||
6459214 | 34 days ago | 0 ETH | ||||
6459214 | 34 days ago | 0 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
InterchainClientV1
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {InterchainClientV1Events} from "./events/InterchainClientV1Events.sol"; import {IExecutionService} from "./interfaces/IExecutionService.sol"; import {IInterchainApp} from "./interfaces/IInterchainApp.sol"; import {IInterchainClientV1} from "./interfaces/IInterchainClientV1.sol"; import {IInterchainDB} from "./interfaces/IInterchainDB.sol"; import {AppConfigV1, AppConfigLib, APP_CONFIG_GUARD_DISABLED, APP_CONFIG_GUARD_DEFAULT} from "./libs/AppConfig.sol"; import {InterchainEntry, InterchainEntryLib, ENTRY_UNVERIFIED, ENTRY_CONFLICT} from "./libs/InterchainEntry.sol"; import { InterchainTransaction, InterchainTxDescriptor, InterchainTransactionLib } from "./libs/InterchainTransaction.sol"; import {OptionsLib, OptionsV1} from "./libs/Options.sol"; import {TypeCasts} from "./libs/TypeCasts.sol"; import {VersionedPayloadLib} from "./libs/VersionedPayload.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; /** * @title InterchainClientV1 * @dev Implements the operations of the Interchain Execution Layer. */ contract InterchainClientV1 is Ownable, InterchainClientV1Events, IInterchainClientV1 { using AppConfigLib for bytes; using OptionsLib for bytes; using TypeCasts for address; using TypeCasts for bytes32; using VersionedPayloadLib for bytes; /// @notice Version of the InterchainClient contract. Sent and received transactions must have the same version. uint16 public constant CLIENT_VERSION = 1; /// @notice Address of the InterchainDB contract, set at the time of deployment. address public immutable INTERCHAIN_DB; /// @notice Address of the Guard module used to verify the validity of entries. /// Note: entries marked as invalid by the Guard could not be used for message execution, /// if the app opts in to use the Guard. address public defaultGuard; /// @notice Address of the default module to use to verify the validity of entries. /// Note: this module will be used for the apps that define an empty module list in their config. address public defaultModule; /// @dev Address of the InterchainClient contract on the remote chain mapping(uint64 chainId => bytes32 remoteClient) internal _linkedClient; /// @dev Executor address that completed the transaction. Address(0) if not executed yet. mapping(bytes32 transactionId => address executor) internal _txExecutor; constructor(address interchainDB, address owner_) Ownable(owner_) { INTERCHAIN_DB = interchainDB; } /// @notice Allows the contract owner to set the address of the Guard module. /// Note: entries marked as invalid by the Guard could not be used for message execution, /// if the app opts in to use the Guard. /// @param guard The address of the Guard module. function setDefaultGuard(address guard) external onlyOwner { if (guard == address(0)) { revert InterchainClientV1__GuardZeroAddress(); } defaultGuard = guard; emit DefaultGuardSet(guard); } /// @notice Allows the contract owner to set the address of the default module. /// Note: this module will be used for the apps that define an empty module list in their config. /// @param module The address of the default module. function setDefaultModule(address module) external onlyOwner { if (module == address(0)) { revert InterchainClientV1__ModuleZeroAddress(); } defaultModule = module; emit DefaultModuleSet(module); } /// @notice Sets the linked client for a specific chain ID. /// Note: only Interchain Entries written by the linked client could be used for message execution. /// @param chainId The chain ID for which the client is being set. /// @param client The address of the client being linked. function setLinkedClient(uint64 chainId, bytes32 client) external onlyOwner { _linkedClient[chainId] = client; emit LinkedClientSet(chainId, client); } /// @notice Sends a message to another chain via the Interchain Communication Protocol. /// @dev Charges a fee for the message, which is payable upon calling this function: /// - Verification fees: paid to every module that verifies the message. /// - Execution fee: paid to the executor that executes the message. /// Note: while a specific execution service is specified to request the execution of the message, /// any executor is able to execute the message on destination chain. /// @param dstChainId The chain ID of the destination chain. /// @param receiver The address of the receiver on the destination chain. /// @param srcExecutionService The address of the execution service to use for the message. /// @param srcModules The source modules involved in the message sending. /// @param options Execution options for the message sent, encoded as bytes, /// currently gas limit + native gas drop. /// @param message The message to be sent. /// @return desc The descriptor of the sent transaction: /// - transactionId: the ID of the transaction that was sent. /// - dbNonce: the database nonce of the entry containing the transaction. function interchainSend( uint64 dstChainId, bytes32 receiver, address srcExecutionService, address[] calldata srcModules, bytes calldata options, bytes calldata message ) external payable returns (InterchainTxDescriptor memory desc) { return _interchainSend(dstChainId, receiver, srcExecutionService, srcModules, options, message); } /// @notice A thin wrapper around `interchainSend` that allows to specify the receiver address as an EVM address. function interchainSendEVM( uint64 dstChainId, address receiver, address srcExecutionService, address[] calldata srcModules, bytes calldata options, bytes calldata message ) external payable returns (InterchainTxDescriptor memory desc) { bytes32 receiverBytes32 = receiver.addressToBytes32(); return _interchainSend(dstChainId, receiverBytes32, srcExecutionService, srcModules, options, message); } /// @notice Executes a transaction that has been sent via the Interchain Communication Protocol. /// Note: The transaction must be proven to be included in one of the InterchainDB entries. /// Note: Transaction data includes the requested gas limit, but the executors could specify a different gas limit. /// If the specified gas limit is lower than requested, the requested gas limit will be used. /// Otherwise, the specified gas limit will be used. /// This allows to execute the transactions with requested gas limit set too low. /// @param gasLimit The gas limit to use for the execution. /// @param transaction The transaction data. function interchainExecute(uint256 gasLimit, bytes calldata transaction) external payable { InterchainTransaction memory icTx = _assertCorrectTransaction(transaction); bytes32 transactionId = keccak256(transaction); _assertExecutable(icTx, transactionId); _txExecutor[transactionId] = msg.sender; OptionsV1 memory decodedOptions = icTx.options.decodeOptionsV1(); if (msg.value != decodedOptions.gasAirdrop) { revert InterchainClientV1__MsgValueMismatch(msg.value, decodedOptions.gasAirdrop); } // We should always use at least as much as the requested gas limit. // The executor can specify a higher gas limit if they wanted. if (decodedOptions.gasLimit > gasLimit) { gasLimit = decodedOptions.gasLimit; } // Check the the Executor has provided big enough gas limit for the whole transaction. uint256 gasLeft = gasleft(); if (gasLeft <= gasLimit) { revert InterchainClientV1__GasLeftBelowMin(gasLeft, gasLimit); } // Pass the full msg.value to the app: we have already checked that it matches the requested gas airdrop. IInterchainApp(icTx.dstReceiver.bytes32ToAddress()).appReceive{gas: gasLimit, value: msg.value}({ srcChainId: icTx.srcChainId, sender: icTx.srcSender, dbNonce: icTx.dbNonce, message: icTx.message }); emit InterchainTransactionReceived({ transactionId: transactionId, dbNonce: icTx.dbNonce, srcChainId: icTx.srcChainId, srcSender: icTx.srcSender, dstReceiver: icTx.dstReceiver }); } /// @notice Writes the proof of execution for a transaction into the InterchainDB. /// @dev Will revert if the transaction has not been executed. /// @param transactionId The ID of the transaction to write the proof for. /// @return dbNonce The database nonce of the entry containing the written proof for transaction. function writeExecutionProof(bytes32 transactionId) external returns (uint64 dbNonce) { address executor = _txExecutor[transactionId]; if (executor == address(0)) { revert InterchainClientV1__TxNotExecuted(transactionId); } bytes memory proof = abi.encode(transactionId, executor); dbNonce = IInterchainDB(INTERCHAIN_DB).writeEntry(keccak256(proof)); emit ExecutionProofWritten({transactionId: transactionId, dbNonce: dbNonce, executor: executor}); } // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════ /// @notice Determines if a transaction meets the criteria to be executed based on: /// - If approved modules have verified the entry in the InterchainDB /// - If the threshold of approved modules have been met /// - If the optimistic window has passed for all modules /// - If the Guard module (if opted in) has not submitted an entry that conflicts with the approved modules /// @dev Will revert with a specific error message if the transaction is not executable. /// @param encodedTx The encoded transaction to check for executable status. function isExecutable(bytes calldata encodedTx) external view returns (bool) { InterchainTransaction memory icTx = _assertCorrectTransaction(encodedTx); // Check that options could be decoded icTx.options.decodeOptionsV1(); bytes32 transactionId = keccak256(encodedTx); _assertExecutable(icTx, transactionId); return true; } /// @notice Returns the readiness status of a transaction to be executed. /// @dev Some of the possible statuses have additional arguments that are returned: /// - Ready: the transaction is ready to be executed. /// - AlreadyExecuted: the transaction has already been executed. /// - `firstArg` is the transaction ID. /// - EntryAwaitingResponses: not enough responses have been received for the transaction. /// - `firstArg` is the number of responses received. /// - `secondArg` is the number of responses required. /// - EntryConflict: one of the modules have submitted a conflicting entry. /// - `firstArg` is the address of the module. /// - This is either one of the modules that the app trusts, or the Guard module used by the app. /// - ReceiverNotICApp: the receiver is not an Interchain app. /// - `firstArg` is the receiver address. /// - TxWrongDstChainId: the destination chain ID does not match the local chain ID. /// - `firstArg` is the destination chain ID. /// - UndeterminedRevert: the transaction will revert for another reason. /// /// Note: the arguments are abi-encoded bytes32 values (as their types could be different). // solhint-disable-next-line code-complexity function getTxReadinessV1(InterchainTransaction memory icTx) external view returns (TxReadiness status, bytes32 firstArg, bytes32 secondArg) { bytes memory encodedTx = encodeTransaction(icTx); try this.isExecutable(encodedTx) returns (bool) { return (TxReadiness.Ready, 0, 0); } catch (bytes memory errorData) { bytes4 selector; (selector, firstArg, secondArg) = _decodeRevertData(errorData); if (selector == InterchainClientV1__TxAlreadyExecuted.selector) { status = TxReadiness.AlreadyExecuted; } else if (selector == InterchainClientV1__ResponsesAmountBelowMin.selector) { status = TxReadiness.EntryAwaitingResponses; } else if (selector == InterchainClientV1__EntryConflict.selector) { status = TxReadiness.EntryConflict; } else if (selector == InterchainClientV1__ReceiverNotICApp.selector) { status = TxReadiness.ReceiverNotICApp; } else if (selector == InterchainClientV1__DstChainIdNotLocal.selector) { status = TxReadiness.TxWrongDstChainId; } else { status = TxReadiness.UndeterminedRevert; firstArg = 0; secondArg = 0; } } } /// @notice Returns the address of the executor for a transaction that has been sent to the local chain. function getExecutor(bytes calldata encodedTx) external view returns (address) { return _txExecutor[keccak256(encodedTx)]; } /// @notice Returns the address of the executor for a transaction that has been sent to the local chain. function getExecutorById(bytes32 transactionId) external view returns (address) { return _txExecutor[transactionId]; } /// @notice Returns the fee for sending an Interchain message. /// @param dstChainId The chain ID of the destination chain. /// @param srcExecutionService The address of the execution service to use for the message. /// @param srcModules The source modules involved in the message sending. /// @param options Execution options for the message sent, currently gas limit + native gas drop. /// @param messageLen The length of the message being sent. function getInterchainFee( uint64 dstChainId, address srcExecutionService, address[] calldata srcModules, bytes calldata options, uint256 messageLen ) external view returns (uint256 fee) { _assertLinkedClient(dstChainId); if (srcExecutionService == address(0)) { revert InterchainClientV1__ExecutionServiceZeroAddress(); } // Check that options could be decoded on destination chain options.decodeOptionsV1(); // Verification fee from InterchainDB fee = IInterchainDB(INTERCHAIN_DB).getInterchainFee(dstChainId, srcModules); // Add execution fee from ExecutionService uint256 payloadSize = InterchainTransactionLib.payloadSize(options.length, messageLen); fee += IExecutionService(srcExecutionService).getExecutionFee(dstChainId, payloadSize, options); } /// @notice Returns the address of the linked client (as bytes32) for a specific chain ID. /// @dev Will return 0x0 if no client is linked for the chain ID. function getLinkedClient(uint64 chainId) external view returns (bytes32) { if (chainId == block.chainid) { revert InterchainClientV1__ChainIdNotRemote(chainId); } return _linkedClient[chainId]; } /// @notice Returns the EVM address of the linked client for a specific chain ID. /// @dev Will return 0x0 if no client is linked for the chain ID. /// Will revert if the client is not an EVM client. function getLinkedClientEVM(uint64 chainId) external view returns (address linkedClientEVM) { if (chainId == block.chainid) { revert InterchainClientV1__ChainIdNotRemote(chainId); } bytes32 linkedClient = _linkedClient[chainId]; linkedClientEVM = linkedClient.bytes32ToAddress(); // Check that the linked client address fits into the EVM address space if (linkedClientEVM.addressToBytes32() != linkedClient) { revert InterchainClientV1__LinkedClientNotEVM(linkedClient); } } /// @notice Decodes the encoded options data into a OptionsV1 struct. function decodeOptions(bytes memory encodedOptions) external view returns (OptionsV1 memory) { return encodedOptions.decodeOptionsV1(); } /// @notice Gets the V1 app config and trusted modules for the receiving app. function getAppReceivingConfigV1(address receiver) public view returns (AppConfigV1 memory config, address[] memory modules) { // First, check that receiver is a contract if (receiver.code.length == 0) { revert InterchainClientV1__ReceiverNotICApp(receiver); } // Then, use a low-level static call to get the config and modules (bool success, bytes memory returnData) = receiver.staticcall(abi.encodeCall(IInterchainApp.getReceivingConfig, ())); if (!success || returnData.length == 0) { revert InterchainClientV1__ReceiverNotICApp(receiver); } bytes memory encodedConfig; (encodedConfig, modules) = abi.decode(returnData, (bytes, address[])); config = encodedConfig.decodeAppConfigV1(); // Fallback to the default module if the app has no modules if (modules.length == 0) { modules = new address[](1); modules[0] = defaultModule; } // Fallback to "all responses" if the app requires zero responses if (config.requiredResponses == 0) { config.requiredResponses = SafeCast.toUint8(modules.length); } } /// @notice Encodes the transaction data into a bytes format. function encodeTransaction(InterchainTransaction memory icTx) public pure returns (bytes memory) { return VersionedPayloadLib.encodeVersionedPayload({ version: CLIENT_VERSION, payload: InterchainTransactionLib.encodeTransaction(icTx) }); } // ═════════════════════════════════════════════════ INTERNAL ══════════════════════════════════════════════════════ /// @dev Internal logic for sending a message to another chain. function _interchainSend( uint64 dstChainId, bytes32 receiver, address srcExecutionService, address[] calldata srcModules, bytes calldata options, bytes calldata message ) internal returns (InterchainTxDescriptor memory desc) { _assertLinkedClient(dstChainId); if (receiver == 0) { revert InterchainClientV1__ReceiverZeroAddress(); } if (srcExecutionService == address(0)) { revert InterchainClientV1__ExecutionServiceZeroAddress(); } // Check that options could be decoded on destination chain options.decodeOptionsV1(); uint256 verificationFee = IInterchainDB(INTERCHAIN_DB).getInterchainFee(dstChainId, srcModules); if (msg.value < verificationFee) { revert InterchainClientV1__FeeAmountBelowMin(msg.value, verificationFee); } desc.dbNonce = IInterchainDB(INTERCHAIN_DB).getDBNonce(); InterchainTransaction memory icTx = InterchainTransactionLib.constructLocalTransaction({ srcSender: msg.sender, dstReceiver: receiver, dstChainId: dstChainId, dbNonce: desc.dbNonce, options: options, message: message }); desc.transactionId = keccak256(encodeTransaction(icTx)); // Sanity check: nonce returned from DB should match the nonce used to construct the transaction { uint64 dbNonce = IInterchainDB(INTERCHAIN_DB).writeEntryRequestVerification{value: verificationFee}( icTx.dstChainId, desc.transactionId, srcModules ); assert(dbNonce == desc.dbNonce); } uint256 executionFee; unchecked { executionFee = msg.value - verificationFee; } IExecutionService(srcExecutionService).requestTxExecution{value: executionFee}({ dstChainId: icTx.dstChainId, txPayloadSize: InterchainTransactionLib.payloadSize(options.length, message.length), transactionId: desc.transactionId, options: options }); emit InterchainTransactionSent({ transactionId: desc.transactionId, dbNonce: desc.dbNonce, dstChainId: icTx.dstChainId, srcSender: icTx.srcSender, dstReceiver: icTx.dstReceiver, verificationFee: verificationFee, executionFee: executionFee, options: icTx.options, message: icTx.message }); } // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════ /// @dev Asserts that the transaction is executable. function _assertExecutable(InterchainTransaction memory icTx, bytes32 transactionId) internal view { bytes32 linkedClient = _assertLinkedClient(icTx.srcChainId); if (_txExecutor[transactionId] != address(0)) { revert InterchainClientV1__TxAlreadyExecuted(transactionId); } // Construct expected entry based on interchain transaction data InterchainEntry memory entry = InterchainEntry({ srcChainId: icTx.srcChainId, dbNonce: icTx.dbNonce, entryValue: InterchainEntryLib.getEntryValue({srcWriter: linkedClient, digest: transactionId}) }); address receiver = icTx.dstReceiver.bytes32ToAddress(); (AppConfigV1 memory appConfig, address[] memory approvedModules) = getAppReceivingConfigV1(receiver); // Note: appConfig.requiredResponses is never zero at this point, see fallbacks in `getAppReceivingConfigV1` // Verify against the Guard if the app opts in to use it address guard = _getGuard(appConfig); _assertNoGuardConflict(guard, entry); // Optimistic period is not used if there's no Guard configured uint256 optimisticSeconds = guard == address(0) ? 0 : appConfig.optimisticSeconds; uint256 finalizedResponses = _getFinalizedResponsesCount(approvedModules, entry, optimisticSeconds); if (finalizedResponses < appConfig.requiredResponses) { revert InterchainClientV1__ResponsesAmountBelowMin(finalizedResponses, appConfig.requiredResponses); } } /// @dev Asserts that the chain is linked and returns the linked client address. function _assertLinkedClient(uint64 chainId) internal view returns (bytes32 linkedClient) { if (chainId == block.chainid) { revert InterchainClientV1__ChainIdNotRemote(chainId); } linkedClient = _linkedClient[chainId]; if (linkedClient == 0) { revert InterchainClientV1__ChainIdNotLinked(chainId); } } /// @dev Asserts that the Guard has not submitted a conflicting entry. function _assertNoGuardConflict(address guard, InterchainEntry memory entry) internal view { if (guard != address(0)) { uint256 confirmedAt = IInterchainDB(INTERCHAIN_DB).checkEntryVerification(guard, entry); if (confirmedAt == ENTRY_CONFLICT) { revert InterchainClientV1__EntryConflict(guard); } } } /// @dev Returns the Guard address to use for the given app config. function _getGuard(AppConfigV1 memory appConfig) internal view returns (address) { if (appConfig.guardFlag == APP_CONFIG_GUARD_DISABLED) { return address(0); } if (appConfig.guardFlag == APP_CONFIG_GUARD_DEFAULT) { return defaultGuard; } return appConfig.guard; } /// @dev Counts the number of finalized responses for the given entry. /// Note: Reverts if a conflicting entry has been verified by any of the approved modules. function _getFinalizedResponsesCount( address[] memory approvedModules, InterchainEntry memory entry, uint256 optimisticSeconds ) internal view returns (uint256 finalizedResponses) { for (uint256 i = 0; i < approvedModules.length; ++i) { address module = approvedModules[i]; uint256 confirmedAt = IInterchainDB(INTERCHAIN_DB).checkEntryVerification(module, entry); // No-op if the module has not verified anything with the same entry key if (confirmedAt == ENTRY_UNVERIFIED) { continue; } // Revert if the module has verified a conflicting entry with the same entry key if (confirmedAt == ENTRY_CONFLICT) { revert InterchainClientV1__EntryConflict(module); } // The module has verified this exact entry, check if optimistic period has passed if (confirmedAt + optimisticSeconds < block.timestamp) { unchecked { ++finalizedResponses; } } } } /// @dev Asserts that the transaction version is correct and that the transaction is for the current chain. /// Note: returns the decoded transaction for chaining purposes. function _assertCorrectTransaction(bytes calldata versionedTx) internal view returns (InterchainTransaction memory icTx) { uint16 version = versionedTx.getVersion(); if (version != CLIENT_VERSION) { revert InterchainClientV1__TxVersionMismatch(version, CLIENT_VERSION); } icTx = InterchainTransactionLib.decodeTransaction(versionedTx.getPayload()); if (icTx.dstChainId != block.chainid) { revert InterchainClientV1__DstChainIdNotLocal(icTx.dstChainId); } } // solhint-disable no-inline-assembly /// @dev Decodes the revert data into a selector and two arguments. /// Zero values are returned if the revert data is not long enough. /// Note: this is only used in `getTxReadinessV1` to decode the revert data, /// so usage of assembly is not a security risk. function _decodeRevertData(bytes memory revertData) internal pure returns (bytes4 selector, bytes32 firstArg, bytes32 secondArg) { // The easiest way to load the bytes chunks onto the stack is to use assembly. // Each time we try to load a value, we check if the revert data is long enough. // We add 0x20 to skip the length field of the revert data. if (revertData.length >= 4) { // Load the first 32 bytes, then apply the mask that has only the 4 highest bytes set. // There is no need to shift, as `bytesN` variables are right-aligned. // https://github.com/ProjectOpenSea/seaport/blob/2ff6ea37/contracts/helpers/SeaportRouter.sol#L161-L175 selector = bytes4(0xFFFFFFFF); assembly { selector := and(mload(add(revertData, 0x20)), selector) } } if (revertData.length >= 36) { // Skip the length field + selector to get the 32 bytes of the first argument. assembly { firstArg := mload(add(revertData, 0x24)) } } if (revertData.length >= 68) { // Skip the length field + selector + first argument to get the 32 bytes of the second argument. assembly { secondArg := mload(add(revertData, 0x44)) } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; abstract contract InterchainClientV1Events { /// @notice Emitted when the default Guard module is set. /// @param guard The address of the Guard module that will be used by default. event DefaultGuardSet(address guard); /// @notice Emitted when the default Module is set. /// @param module The address of the Module that will be used by default. event DefaultModuleSet(address module); /// @notice Emitted when the InterchainClientV1 deployment on a remote chain is linked. /// @param chainId The chain ID of the remote chain. /// @param client The address of the InterchainClientV1 deployment on the remote chain. event LinkedClientSet(uint64 chainId, bytes32 client); /// @notice Emitted when a new interchain transaction is sent through the InterchainClientV1. /// The Receiver on the destination chain will receive the specified message once the transaction is executed. /// @param transactionId The unique identifier of the interchain transaction. /// @param dbNonce The nonce of entry containing the transaction. /// @param dstChainId The chain ID of the destination chain. /// @param srcSender The sender of the transaction on the source chain. /// @param dstReceiver The receiver of the transaction on the destination chain. /// @param verificationFee The fee paid to verify the entry on the destination chain. /// @param executionFee The fee paid to execute the transaction on the destination chain. /// @param options The execution options for the transaction. /// @param message The payload of the message being sent. event InterchainTransactionSent( bytes32 indexed transactionId, uint64 dbNonce, uint64 dstChainId, bytes32 indexed srcSender, bytes32 indexed dstReceiver, uint256 verificationFee, uint256 executionFee, bytes options, bytes message ); /// @notice Emitted when an interchain transaction is received by the InterchainClientV1. /// The Receiver on the destination chain has just received the message sent from the source chain. /// @param transactionId The unique identifier of the interchain transaction. /// @param dbNonce The nonce of entry containing the transaction. /// @param srcChainId The chain ID of the source chain. /// @param srcSender The sender of the transaction on the source chain. /// @param dstReceiver The receiver of the transaction on the destination chain. event InterchainTransactionReceived( bytes32 indexed transactionId, uint64 dbNonce, uint64 srcChainId, bytes32 indexed srcSender, bytes32 indexed dstReceiver ); /// @notice Emitted when the proof of execution is written to InterchainDB. This allows the source chain /// to verify that the transaction was executed by a specific executor, if necessary. /// @param transactionId The unique identifier of the interchain transaction. /// @param dbNonce The nonce of entry containing the transaction. /// @param executor The address of the executor that completed the transaction. event ExecutionProofWritten(bytes32 indexed transactionId, uint64 dbNonce, address indexed executor); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IExecutionService { function requestTxExecution( uint64 dstChainId, uint256 txPayloadSize, bytes32 transactionId, bytes memory options ) external payable; // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════ function executorEOA() external view returns (address); function getExecutionFee( uint64 dstChainId, uint256 txPayloadSize, bytes memory options ) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @notice Minimal interface for the Interchain App to work with the Interchain Client. interface IInterchainApp { function appReceive(uint64 srcChainId, bytes32 sender, uint64 dbNonce, bytes calldata message) external payable; // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════ function getReceivingConfig() external view returns (bytes memory appConfig, address[] memory modules); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {InterchainTransaction, InterchainTxDescriptor} from "../libs/InterchainTransaction.sol"; interface IInterchainClientV1 { enum TxReadiness { Ready, AlreadyExecuted, EntryAwaitingResponses, EntryConflict, ReceiverNotICApp, TxWrongDstChainId, UndeterminedRevert } error InterchainClientV1__ChainIdNotLinked(uint64 chainId); error InterchainClientV1__ChainIdNotRemote(uint64 chainId); error InterchainClientV1__DstChainIdNotLocal(uint64 chainId); error InterchainClientV1__EntryConflict(address module); error InterchainClientV1__ExecutionServiceZeroAddress(); error InterchainClientV1__FeeAmountBelowMin(uint256 feeAmount, uint256 minRequired); error InterchainClientV1__GasLeftBelowMin(uint256 gasLeft, uint256 minRequired); error InterchainClientV1__GuardZeroAddress(); error InterchainClientV1__LinkedClientNotEVM(bytes32 client); error InterchainClientV1__ModuleZeroAddress(); error InterchainClientV1__MsgValueMismatch(uint256 msgValue, uint256 required); error InterchainClientV1__ReceiverNotICApp(address receiver); error InterchainClientV1__ReceiverZeroAddress(); error InterchainClientV1__ResponsesAmountBelowMin(uint256 responsesAmount, uint256 minRequired); error InterchainClientV1__TxAlreadyExecuted(bytes32 transactionId); error InterchainClientV1__TxNotExecuted(bytes32 transactionId); error InterchainClientV1__TxVersionMismatch(uint16 txVersion, uint16 required); function setDefaultGuard(address guard) external; function setDefaultModule(address module) external; function setLinkedClient(uint64 chainId, bytes32 client) external; function interchainSend( uint64 dstChainId, bytes32 receiver, address srcExecutionService, address[] calldata srcModules, bytes calldata options, bytes calldata message ) external payable returns (InterchainTxDescriptor memory desc); function interchainSendEVM( uint64 dstChainId, address receiver, address srcExecutionService, address[] calldata srcModules, bytes calldata options, bytes calldata message ) external payable returns (InterchainTxDescriptor memory desc); function interchainExecute(uint256 gasLimit, bytes calldata transaction) external payable; function writeExecutionProof(bytes32 transactionId) external returns (uint64 dbNonce); // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════ function isExecutable(bytes calldata transaction) external view returns (bool); function getTxReadinessV1(InterchainTransaction memory icTx) external view returns (TxReadiness status, bytes32 firstArg, bytes32 secondArg); function getInterchainFee( uint64 dstChainId, address srcExecutionService, address[] calldata srcModules, bytes calldata options, uint256 messageLen ) external view returns (uint256); function getExecutor(bytes calldata transaction) external view returns (address); function getExecutorById(bytes32 transactionId) external view returns (address); function getLinkedClient(uint64 chainId) external view returns (bytes32); function getLinkedClientEVM(uint64 chainId) external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {InterchainEntry} from "../libs/InterchainEntry.sol"; interface IInterchainDB { error InterchainDB__ChainIdNotRemote(uint64 chainId); error InterchainDB__EntryConflict(address module, InterchainEntry newEntry); error InterchainDB__EntryVersionMismatch(uint16 version, uint16 required); error InterchainDB__FeeAmountBelowMin(uint256 feeAmount, uint256 minRequired); error InterchainDB__ModulesNotProvided(); function writeEntry(bytes32 digest) external returns (uint64 dbNonce); function requestEntryVerification( uint64 dstChainId, uint64 dbNonce, address[] memory srcModules ) external payable; function writeEntryRequestVerification( uint64 dstChainId, bytes32 digest, address[] memory srcModules ) external payable returns (uint64 dbNonce); function verifyRemoteEntry(bytes memory encodedEntry) external; // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════ function getInterchainFee(uint64 dstChainId, address[] memory srcModules) external view returns (uint256); function getEncodedEntry(uint64 dbNonce) external view returns (bytes memory); function getEntry(uint64 dbNonce) external view returns (InterchainEntry memory); function getEntryValue(uint64 dbNonce) external view returns (bytes32); function getDBNonce() external view returns (uint64); function checkEntryVerification( address dstModule, InterchainEntry memory entry ) external view returns (uint256 moduleVerifiedAt); // solhint-disable-next-line func-name-mixedcase function DB_VERSION() external pure returns (uint16); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {VersionedPayloadLib} from "./VersionedPayload.sol"; struct AppConfigV1 { uint8 requiredResponses; uint48 optimisticSeconds; uint8 guardFlag; address guard; } using AppConfigLib for AppConfigV1 global; /// @dev Signals that the app opted out of using any Guard module. uint8 constant APP_CONFIG_GUARD_DISABLED = 0; /// @dev Signals that the app uses the default Guard module provided by InterchainClient contract. uint8 constant APP_CONFIG_GUARD_DEFAULT = 1; /// @dev Signals that the app uses a custom Guard module. uint8 constant APP_CONFIG_GUARD_CUSTOM = 2; library AppConfigLib { using VersionedPayloadLib for bytes; uint16 internal constant APP_CONFIG_V1 = 1; error AppConfigLib__VersionInvalid(uint16 version); /// @notice Decodes app config (V1 or higher) from a bytes format back into an AppConfigV1 struct. /// @param data The app config data in bytes format. function decodeAppConfigV1(bytes memory data) internal view returns (AppConfigV1 memory) { uint16 version = data.getVersionFromMemory(); if (version < APP_CONFIG_V1) { revert AppConfigLib__VersionInvalid(version); } // Structs of the same version will always be decoded correctly. // Following versions will be decoded correctly if they have the same fields as the previous version, // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload. return abi.decode(data.getPayloadFromMemory(), (AppConfigV1)); } /// @notice Encodes V1 app config into a bytes format. /// @param appConfig The AppConfigV1 to encode. function encodeAppConfigV1(AppConfigV1 memory appConfig) internal pure returns (bytes memory) { return VersionedPayloadLib.encodeVersionedPayload(APP_CONFIG_V1, abi.encode(appConfig)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; /// @notice Struct representing an entry in the Interchain DataBase. /// Entry has a globally unique identifier (key) and a value. /// Assuming `srcWriter` has written data `digest` on the source chain: /// - key: (srcChainId, dbNonce) /// - entryValue = keccak256(srcWriter, digest) /// @param srcChainId The chain id of the source chain /// @param dbNonce The database nonce of the entry /// @param entryValue The entry value struct InterchainEntry { uint64 srcChainId; uint64 dbNonce; bytes32 entryValue; } type EntryKey is uint128; /// @dev Signals that the module has not verified any entry with the given key. uint256 constant ENTRY_UNVERIFIED = 0; /// @dev Signals that the module has verified a conflicting entry with the given key. uint256 constant ENTRY_CONFLICT = type(uint256).max; library InterchainEntryLib { /// @notice Constructs an InterchainEntry struct to be written on the local chain /// @param dbNonce The database nonce of the entry on the source chain /// @param entryValue The value of the entry /// @return entry The constructed InterchainEntry struct function constructLocalEntry( uint64 dbNonce, bytes32 entryValue ) internal view returns (InterchainEntry memory entry) { uint64 srcChainId = SafeCast.toUint64(block.chainid); return InterchainEntry({srcChainId: srcChainId, dbNonce: dbNonce, entryValue: entryValue}); } /// @notice Returns the value of the entry: writer + digest hashed together function getEntryValue(bytes32 srcWriter, bytes32 digest) internal pure returns (bytes32) { return keccak256(abi.encode(srcWriter, digest)); } /// @notice Returns the value of the entry: writer + digest hashed together. /// Note: this is exposed for convenience to avoid typecasts prior to abi-encoding. function getEntryValue(address srcWriter, bytes32 digest) internal pure returns (bytes32) { return keccak256(abi.encode(srcWriter, digest)); } /// @notice Encodes the InterchainEntry struct into a non-versioned entry payload. function encodeEntry(InterchainEntry memory entry) internal pure returns (bytes memory) { return abi.encode(encodeEntryKey(entry.srcChainId, entry.dbNonce), entry.entryValue); } /// @notice Decodes the InterchainEntry struct from a non-versioned entry payload in calldata. function decodeEntry(bytes calldata data) internal pure returns (InterchainEntry memory entry) { EntryKey key; (key, entry.entryValue) = abi.decode(data, (EntryKey, bytes32)); (entry.srcChainId, entry.dbNonce) = decodeEntryKey(key); } /// @notice Decodes the InterchainEntry struct from a non-versioned entry payload in memory. function decodeEntryFromMemory(bytes memory data) internal pure returns (InterchainEntry memory entry) { EntryKey key; (key, entry.entryValue) = abi.decode(data, (EntryKey, bytes32)); (entry.srcChainId, entry.dbNonce) = decodeEntryKey(key); } /// @notice Encodes the uint128 key of the entry from uint64 srcChainId and uint64 dbNonce. function encodeEntryKey(uint64 srcChainId, uint64 dbNonce) internal pure returns (EntryKey) { return EntryKey.wrap((uint128(srcChainId) << 64) | dbNonce); } /// @notice Decodes the uint128 key of the entry into uint64 srcChainId and uint64 dbNonce. function decodeEntryKey(EntryKey key) internal pure returns (uint64 srcChainId, uint64 dbNonce) { srcChainId = uint64(EntryKey.unwrap(key) >> 64); dbNonce = uint64(EntryKey.unwrap(key)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {MathLib} from "./Math.sol"; import {TypeCasts} from "./TypeCasts.sol"; import {VersionedPayloadLib} from "./VersionedPayload.sol"; import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; type ICTxHeader is uint256; struct InterchainTransaction { uint64 srcChainId; uint64 dstChainId; uint64 dbNonce; bytes32 srcSender; bytes32 dstReceiver; bytes options; bytes message; } struct InterchainTxDescriptor { bytes32 transactionId; uint64 dbNonce; } using InterchainTransactionLib for InterchainTransaction global; library InterchainTransactionLib { using MathLib for uint256; using VersionedPayloadLib for bytes; function constructLocalTransaction( address srcSender, uint64 dstChainId, bytes32 dstReceiver, uint64 dbNonce, bytes memory options, bytes memory message ) internal view returns (InterchainTransaction memory transaction) { return InterchainTransaction({ srcChainId: SafeCast.toUint64(block.chainid), srcSender: TypeCasts.addressToBytes32(srcSender), dstChainId: dstChainId, dstReceiver: dstReceiver, dbNonce: dbNonce, options: options, message: message }); } function encodeTransaction(InterchainTransaction memory transaction) internal pure returns (bytes memory) { return abi.encode( encodeTxHeader(transaction.srcChainId, transaction.dstChainId, transaction.dbNonce), transaction.srcSender, transaction.dstReceiver, transaction.options, transaction.message ); } function decodeTransaction(bytes calldata transaction) internal pure returns (InterchainTransaction memory icTx) { ICTxHeader header; (header, icTx.srcSender, icTx.dstReceiver, icTx.options, icTx.message) = abi.decode(transaction, (ICTxHeader, bytes32, bytes32, bytes, bytes)); (icTx.srcChainId, icTx.dstChainId, icTx.dbNonce) = decodeTxHeader(header); } function payloadSize(uint256 optionsLen, uint256 messageLen) internal pure returns (uint256) { // 2 bytes are reserved for the transaction version // + 5 fields * 32 bytes (3 values for static, 2 offsets for dynamic) + 2 * 32 bytes (lengths for dynamic) = 226 // (srcChainId, dstChainId, dbNonce) are merged into a single 32 bytes field // Both options and message are dynamic fields, which are padded up to 32 bytes return 226 + optionsLen.roundUpToWord() + messageLen.roundUpToWord(); } function encodeTxHeader(uint64 srcChainId, uint64 dstChainId, uint64 dbNonce) internal pure returns (ICTxHeader) { return ICTxHeader.wrap((uint256(srcChainId) << 128) | (uint256(dstChainId) << 64) | (uint256(dbNonce))); } function decodeTxHeader(ICTxHeader header) internal pure returns (uint64 srcChainId, uint64 dstChainId, uint64 dbNonce) { srcChainId = uint64(ICTxHeader.unwrap(header) >> 128); dstChainId = uint64(ICTxHeader.unwrap(header) >> 64); dbNonce = uint64(ICTxHeader.unwrap(header)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {VersionedPayloadLib} from "./VersionedPayload.sol"; /// @notice Struct to hold V1 of options data. /// @dev Next versions have to use the fields from the previous version and add new fields at the end. /// @param gasLimit The gas limit for the transaction. /// @param gasAirdrop The amount of gas to airdrop. struct OptionsV1 { uint256 gasLimit; uint256 gasAirdrop; } using OptionsLib for OptionsV1 global; /// @title OptionsLib /// @notice A library for encoding and decoding Interchain options related to interchain messages. library OptionsLib { using VersionedPayloadLib for bytes; uint16 internal constant OPTIONS_V1 = 1; error OptionsLib__VersionInvalid(uint16 version); /// @notice Decodes options (V1 or higher) from a bytes format back into an OptionsV1 struct. /// @param data The options data in bytes format. function decodeOptionsV1(bytes memory data) internal view returns (OptionsV1 memory) { uint16 version = data.getVersionFromMemory(); if (version < OPTIONS_V1) { revert OptionsLib__VersionInvalid(version); } // Structs of the same version will always be decoded correctly. // Following versions will be decoded correctly if they have the same fields as the previous version, // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload. return abi.decode(data.getPayloadFromMemory(), (OptionsV1)); } /// @notice Encodes V1 options into a bytes format. /// @param options The OptionsV1 to encode. function encodeOptionsV1(OptionsV1 memory options) internal pure returns (bytes memory) { return VersionedPayloadLib.encodeVersionedPayload(OPTIONS_V1, abi.encode(options)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; library TypeCasts { function addressToBytes32(address addr) internal pure returns (bytes32) { return bytes32(uint256(uint160(addr))); } function bytes32ToAddress(bytes32 b) internal pure returns (address) { return address(uint160(uint256(b))); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; // solhint-disable no-inline-assembly // solhint-disable ordering library VersionedPayloadLib { /// @notice Amount of bytes reserved for the version (uint16) in the versioned payload uint256 internal constant VERSION_LENGTH = 2; error VersionedPayload__PayloadTooShort(bytes versionedPayload); error VersionedPayload__PrecompileFailed(); /// @notice Encodes the versioned payload into a single bytes array. /// @param version The payload's version. /// @param payload The payload to encode. function encodeVersionedPayload(uint16 version, bytes memory payload) internal pure returns (bytes memory) { return abi.encodePacked(version, payload); } /// @notice Extracts the version from the versioned payload (calldata reference). /// @param versionedPayload The versioned payload (calldata reference). function getVersion(bytes calldata versionedPayload) internal pure returns (uint16 version) { if (versionedPayload.length < VERSION_LENGTH) { revert VersionedPayload__PayloadTooShort(versionedPayload); } assembly { // We are only interested in the highest 16 bits of the loaded full 32 bytes word. version := shr(240, calldataload(versionedPayload.offset)) } } /// @notice Extracts the payload from the versioned payload (calldata reference). /// @dev The extracted payload is also returned as a calldata reference. /// @param versionedPayload The versioned payload. function getPayload(bytes calldata versionedPayload) internal pure returns (bytes calldata) { if (versionedPayload.length < VERSION_LENGTH) { revert VersionedPayload__PayloadTooShort(versionedPayload); } return versionedPayload[VERSION_LENGTH:]; } /// @notice Extracts the version from the versioned payload (memory reference). /// @param versionedPayload The versioned payload (memory reference). function getVersionFromMemory(bytes memory versionedPayload) internal pure returns (uint16 version) { if (versionedPayload.length < VERSION_LENGTH) { revert VersionedPayload__PayloadTooShort(versionedPayload); } assembly { // We are only interested in the highest 16 bits of the loaded full 32 bytes word. // We add 0x20 to skip the length of the bytes array. version := shr(240, mload(add(versionedPayload, 0x20))) } } /// @notice Extracts the payload from the versioned payload (memory reference). /// @dev The extracted payload is copied into a new memory location. Use `getPayload` when possible /// to avoid extra memory allocation. /// @param versionedPayload The versioned payload (memory reference). function getPayloadFromMemory(bytes memory versionedPayload) internal view returns (bytes memory payload) { if (versionedPayload.length < VERSION_LENGTH) { revert VersionedPayload__PayloadTooShort(versionedPayload); } // Figure how many bytes to copy and allocate the memory for the extracted payload. uint256 toCopy; unchecked { toCopy = versionedPayload.length - VERSION_LENGTH; } payload = new bytes(toCopy); // Use identity precompile (0x04) to copy the payload. Unlike MCOPY, this is available on all EVM chains. bool res; assembly { // We add 0x20 to skip the length of the bytes array. // We add 0x02 to skip the 2 bytes reserved for the version. // Copy the payload to the previously allocated memory. res := staticcall(gas(), 0x04, add(versionedPayload, 0x22), toCopy, add(payload, 0x20), toCopy) } if (!res) { revert VersionedPayload__PrecompileFailed(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.20; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeCast { /** * @dev Value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** * @dev An int value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedIntToUint(int256 value); /** * @dev Value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** * @dev An uint value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedUintToInt(uint256 value); /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits */ function toUint248(uint256 value) internal pure returns (uint248) { if (value > type(uint248).max) { revert SafeCastOverflowedUintDowncast(248, value); } return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits */ function toUint240(uint256 value) internal pure returns (uint240) { if (value > type(uint240).max) { revert SafeCastOverflowedUintDowncast(240, value); } return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits */ function toUint232(uint256 value) internal pure returns (uint232) { if (value > type(uint232).max) { revert SafeCastOverflowedUintDowncast(232, value); } return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { if (value > type(uint224).max) { revert SafeCastOverflowedUintDowncast(224, value); } return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits */ function toUint216(uint256 value) internal pure returns (uint216) { if (value > type(uint216).max) { revert SafeCastOverflowedUintDowncast(216, value); } return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits */ function toUint208(uint256 value) internal pure returns (uint208) { if (value > type(uint208).max) { revert SafeCastOverflowedUintDowncast(208, value); } return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits */ function toUint200(uint256 value) internal pure returns (uint200) { if (value > type(uint200).max) { revert SafeCastOverflowedUintDowncast(200, value); } return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits */ function toUint192(uint256 value) internal pure returns (uint192) { if (value > type(uint192).max) { revert SafeCastOverflowedUintDowncast(192, value); } return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits */ function toUint184(uint256 value) internal pure returns (uint184) { if (value > type(uint184).max) { revert SafeCastOverflowedUintDowncast(184, value); } return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits */ function toUint176(uint256 value) internal pure returns (uint176) { if (value > type(uint176).max) { revert SafeCastOverflowedUintDowncast(176, value); } return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits */ function toUint168(uint256 value) internal pure returns (uint168) { if (value > type(uint168).max) { revert SafeCastOverflowedUintDowncast(168, value); } return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits */ function toUint160(uint256 value) internal pure returns (uint160) { if (value > type(uint160).max) { revert SafeCastOverflowedUintDowncast(160, value); } return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits */ function toUint152(uint256 value) internal pure returns (uint152) { if (value > type(uint152).max) { revert SafeCastOverflowedUintDowncast(152, value); } return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits */ function toUint144(uint256 value) internal pure returns (uint144) { if (value > type(uint144).max) { revert SafeCastOverflowedUintDowncast(144, value); } return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits */ function toUint136(uint256 value) internal pure returns (uint136) { if (value > type(uint136).max) { revert SafeCastOverflowedUintDowncast(136, value); } return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { if (value > type(uint128).max) { revert SafeCastOverflowedUintDowncast(128, value); } return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits */ function toUint120(uint256 value) internal pure returns (uint120) { if (value > type(uint120).max) { revert SafeCastOverflowedUintDowncast(120, value); } return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits */ function toUint112(uint256 value) internal pure returns (uint112) { if (value > type(uint112).max) { revert SafeCastOverflowedUintDowncast(112, value); } return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits */ function toUint104(uint256 value) internal pure returns (uint104) { if (value > type(uint104).max) { revert SafeCastOverflowedUintDowncast(104, value); } return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { if (value > type(uint96).max) { revert SafeCastOverflowedUintDowncast(96, value); } return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits */ function toUint88(uint256 value) internal pure returns (uint88) { if (value > type(uint88).max) { revert SafeCastOverflowedUintDowncast(88, value); } return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits */ function toUint80(uint256 value) internal pure returns (uint80) { if (value > type(uint80).max) { revert SafeCastOverflowedUintDowncast(80, value); } return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits */ function toUint72(uint256 value) internal pure returns (uint72) { if (value > type(uint72).max) { revert SafeCastOverflowedUintDowncast(72, value); } return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { if (value > type(uint64).max) { revert SafeCastOverflowedUintDowncast(64, value); } return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits */ function toUint56(uint256 value) internal pure returns (uint56) { if (value > type(uint56).max) { revert SafeCastOverflowedUintDowncast(56, value); } return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits */ function toUint48(uint256 value) internal pure returns (uint48) { if (value > type(uint48).max) { revert SafeCastOverflowedUintDowncast(48, value); } return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits */ function toUint40(uint256 value) internal pure returns (uint40) { if (value > type(uint40).max) { revert SafeCastOverflowedUintDowncast(40, value); } return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { if (value > type(uint32).max) { revert SafeCastOverflowedUintDowncast(32, value); } return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits */ function toUint24(uint256 value) internal pure returns (uint24) { if (value > type(uint24).max) { revert SafeCastOverflowedUintDowncast(24, value); } return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { if (value > type(uint16).max) { revert SafeCastOverflowedUintDowncast(16, value); } return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits */ function toUint8(uint256 value) internal pure returns (uint8) { if (value > type(uint8).max) { revert SafeCastOverflowedUintDowncast(8, value); } return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { if (value < 0) { revert SafeCastOverflowedIntToUint(value); } return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(248, value); } } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(240, value); } } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(232, value); } } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(224, value); } } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(216, value); } } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(208, value); } } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(200, value); } } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(192, value); } } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(184, value); } } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(176, value); } } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(168, value); } } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(160, value); } } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(152, value); } } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(144, value); } } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(136, value); } } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(128, value); } } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(120, value); } } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(112, value); } } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(104, value); } } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(96, value); } } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(88, value); } } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(80, value); } } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(72, value); } } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(64, value); } } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(56, value); } } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(48, value); } } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(40, value); } } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(32, value); } } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(24, value); } } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(16, value); } } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(8, value); } } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive if (value > uint256(type(int256).max)) { revert SafeCastOverflowedUintToInt(value); } return int256(value); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; library MathLib { /// @notice Rounds up to the nearest multiple of 32. /// Note: Returns zero on overflows instead of reverting. This is fine for practical /// use cases, as this is used for determining the size of the payload in memory. function roundUpToWord(uint256 x) internal pure returns (uint256) { unchecked { return (x + 31) & ~uint256(31); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
{ "remappings": [ "@openzeppelin/=node_modules/@openzeppelin/", "@synapsecns/=node_modules/@synapsecns/", "forge-std/=node_modules/forge-std/src/" ], "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": {} }
[{"inputs":[{"internalType":"address","name":"interchainDB","type":"address"},{"internalType":"address","name":"owner_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint16","name":"version","type":"uint16"}],"name":"AppConfigLib__VersionInvalid","type":"error"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"InterchainClientV1__ChainIdNotLinked","type":"error"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"InterchainClientV1__ChainIdNotRemote","type":"error"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"InterchainClientV1__DstChainIdNotLocal","type":"error"},{"inputs":[{"internalType":"address","name":"module","type":"address"}],"name":"InterchainClientV1__EntryConflict","type":"error"},{"inputs":[],"name":"InterchainClientV1__ExecutionServiceZeroAddress","type":"error"},{"inputs":[{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"uint256","name":"minRequired","type":"uint256"}],"name":"InterchainClientV1__FeeAmountBelowMin","type":"error"},{"inputs":[{"internalType":"uint256","name":"gasLeft","type":"uint256"},{"internalType":"uint256","name":"minRequired","type":"uint256"}],"name":"InterchainClientV1__GasLeftBelowMin","type":"error"},{"inputs":[],"name":"InterchainClientV1__GuardZeroAddress","type":"error"},{"inputs":[{"internalType":"bytes32","name":"client","type":"bytes32"}],"name":"InterchainClientV1__LinkedClientNotEVM","type":"error"},{"inputs":[],"name":"InterchainClientV1__ModuleZeroAddress","type":"error"},{"inputs":[{"internalType":"uint256","name":"msgValue","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"InterchainClientV1__MsgValueMismatch","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"InterchainClientV1__ReceiverNotICApp","type":"error"},{"inputs":[],"name":"InterchainClientV1__ReceiverZeroAddress","type":"error"},{"inputs":[{"internalType":"uint256","name":"responsesAmount","type":"uint256"},{"internalType":"uint256","name":"minRequired","type":"uint256"}],"name":"InterchainClientV1__ResponsesAmountBelowMin","type":"error"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"InterchainClientV1__TxAlreadyExecuted","type":"error"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"InterchainClientV1__TxNotExecuted","type":"error"},{"inputs":[{"internalType":"uint16","name":"txVersion","type":"uint16"},{"internalType":"uint16","name":"required","type":"uint16"}],"name":"InterchainClientV1__TxVersionMismatch","type":"error"},{"inputs":[{"internalType":"uint16","name":"version","type":"uint16"}],"name":"OptionsLib__VersionInvalid","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"uint8","name":"bits","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"SafeCastOverflowedUintDowncast","type":"error"},{"inputs":[{"internalType":"bytes","name":"versionedPayload","type":"bytes"}],"name":"VersionedPayload__PayloadTooShort","type":"error"},{"inputs":[],"name":"VersionedPayload__PrecompileFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guard","type":"address"}],"name":"DefaultGuardSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"module","type":"address"}],"name":"DefaultModuleSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"dbNonce","type":"uint64"},{"indexed":true,"internalType":"address","name":"executor","type":"address"}],"name":"ExecutionProofWritten","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"dbNonce","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"srcChainId","type":"uint64"},{"indexed":true,"internalType":"bytes32","name":"srcSender","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"dstReceiver","type":"bytes32"}],"name":"InterchainTransactionReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"dbNonce","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"dstChainId","type":"uint64"},{"indexed":true,"internalType":"bytes32","name":"srcSender","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"dstReceiver","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"verificationFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"executionFee","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"options","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"message","type":"bytes"}],"name":"InterchainTransactionSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"client","type":"bytes32"}],"name":"LinkedClientSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"CLIENT_VERSION","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INTERCHAIN_DB","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedOptions","type":"bytes"}],"name":"decodeOptions","outputs":[{"components":[{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"gasAirdrop","type":"uint256"}],"internalType":"struct OptionsV1","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultGuard","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultModule","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"uint64","name":"dbNonce","type":"uint64"},{"internalType":"bytes32","name":"srcSender","type":"bytes32"},{"internalType":"bytes32","name":"dstReceiver","type":"bytes32"},{"internalType":"bytes","name":"options","type":"bytes"},{"internalType":"bytes","name":"message","type":"bytes"}],"internalType":"struct InterchainTransaction","name":"icTx","type":"tuple"}],"name":"encodeTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"getAppReceivingConfigV1","outputs":[{"components":[{"internalType":"uint8","name":"requiredResponses","type":"uint8"},{"internalType":"uint48","name":"optimisticSeconds","type":"uint48"},{"internalType":"uint8","name":"guardFlag","type":"uint8"},{"internalType":"address","name":"guard","type":"address"}],"internalType":"struct AppConfigV1","name":"config","type":"tuple"},{"internalType":"address[]","name":"modules","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedTx","type":"bytes"}],"name":"getExecutor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"getExecutorById","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address","name":"srcExecutionService","type":"address"},{"internalType":"address[]","name":"srcModules","type":"address[]"},{"internalType":"bytes","name":"options","type":"bytes"},{"internalType":"uint256","name":"messageLen","type":"uint256"}],"name":"getInterchainFee","outputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"getLinkedClient","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"getLinkedClientEVM","outputs":[{"internalType":"address","name":"linkedClientEVM","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"uint64","name":"dbNonce","type":"uint64"},{"internalType":"bytes32","name":"srcSender","type":"bytes32"},{"internalType":"bytes32","name":"dstReceiver","type":"bytes32"},{"internalType":"bytes","name":"options","type":"bytes"},{"internalType":"bytes","name":"message","type":"bytes"}],"internalType":"struct InterchainTransaction","name":"icTx","type":"tuple"}],"name":"getTxReadinessV1","outputs":[{"internalType":"enum IInterchainClientV1.TxReadiness","name":"status","type":"uint8"},{"internalType":"bytes32","name":"firstArg","type":"bytes32"},{"internalType":"bytes32","name":"secondArg","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"bytes","name":"transaction","type":"bytes"}],"name":"interchainExecute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"bytes32","name":"receiver","type":"bytes32"},{"internalType":"address","name":"srcExecutionService","type":"address"},{"internalType":"address[]","name":"srcModules","type":"address[]"},{"internalType":"bytes","name":"options","type":"bytes"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"interchainSend","outputs":[{"components":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"uint64","name":"dbNonce","type":"uint64"}],"internalType":"struct InterchainTxDescriptor","name":"desc","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"srcExecutionService","type":"address"},{"internalType":"address[]","name":"srcModules","type":"address[]"},{"internalType":"bytes","name":"options","type":"bytes"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"interchainSendEVM","outputs":[{"components":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"uint64","name":"dbNonce","type":"uint64"}],"internalType":"struct InterchainTxDescriptor","name":"desc","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedTx","type":"bytes"}],"name":"isExecutable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"guard","type":"address"}],"name":"setDefaultGuard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"module","type":"address"}],"name":"setDefaultModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"bytes32","name":"client","type":"bytes32"}],"name":"setLinkedClient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"writeExecutionProof","outputs":[{"internalType":"uint64","name":"dbNonce","type":"uint64"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b5060405162002d3e38038062002d3e8339810160408190526200003491620000f0565b806001600160a01b0381166200006457604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6200006f8162000083565b50506001600160a01b031660805262000128565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b0381168114620000eb57600080fd5b919050565b600080604083850312156200010457600080fd5b6200010f83620000d3565b91506200011f60208401620000d3565b90509250929050565b608051612bc9620001756000396000818161042b01528181610cd801528181610ea70152818161144f015281816114f70152818161163001528181611c510152611d2d0152612bc96000f3fe60806040526004361061014b5760003560e01c80638da5cb5b116100b6578063e4c612471161006f578063e4c6124714610419578063f06c79771461044d578063f1a61fac1461047a578063f2fde38b146104b0578063f3c66e2b146104d0578063f92a79ff146104f057600080fd5b80638da5cb5b1461032857806390e810771461034657806394bf49f41461037e578063cbb3c6311461039e578063d5e788a0146103be578063e4344069146103f957600080fd5b80633f34448e116101085780633f34448e14610260578063547efb8414610297578063695fd54f146102aa578063715018a6146102d85780637813cd52146102ed57806380efe7771461031557600080fd5b80630a24bb93146101505780632a20521e146101885780632e568739146101c057806331afa7de146101ee57806335c4a1911461021e5780633d677ed01461023e575b600080fd5b34801561015c57600080fd5b5061017061016b366004612018565b610510565b60405161017f939291906120ef565b60405180910390f35b34801561019457600080fd5b506001546101a8906001600160a01b031681565b6040516001600160a01b03909116815260200161017f565b3480156101cc57600080fd5b506101e06101db366004612125565b610697565b60405190815260200161017f565b3480156101fa57600080fd5b5061020e610209366004612183565b6106ee565b604051901515815260200161017f565b34801561022a57600080fd5b506101a8610239366004612125565b61073e565b34801561024a57600080fd5b5061025e6102593660046121d9565b6107c1565b005b61027361026e36600461223a565b610845565b60408051825181526020928301516001600160401b0316928101929092520161017f565b6102736102a536600461230d565b610883565b3480156102b657600080fd5b506102ca6102c53660046121d9565b6108b6565b60405161017f92919061234d565b3480156102e457600080fd5b5061025e610a82565b3480156102f957600080fd5b50610302600181565b60405161ffff909116815260200161017f565b61025e6103233660046123d9565b610a96565b34801561033457600080fd5b506000546001600160a01b03166101a8565b34801561035257600080fd5b50610366610361366004612424565b610c4d565b6040516001600160401b03909116815260200161017f565b34801561038a57600080fd5b5061025e6103993660046121d9565b610da0565b3480156103aa57600080fd5b506101e06103b936600461243d565b610e1d565b3480156103ca57600080fd5b506103de6103d93660046124da565b610fbc565b6040805182518152602092830151928101929092520161017f565b34801561040557600080fd5b506002546101a8906001600160a01b031681565b34801561042557600080fd5b506101a87f000000000000000000000000000000000000000000000000000000000000000081565b34801561045957600080fd5b5061046d610468366004612018565b610fd9565b60405161017f9190612566565b34801561048657600080fd5b506101a8610495366004612424565b6000908152600460205260409020546001600160a01b031690565b3480156104bc57600080fd5b5061025e6104cb3660046121d9565b610fee565b3480156104dc57600080fd5b5061025e6104eb366004612579565b61102c565b3480156104fc57600080fd5b506101a861050b366004612183565b61108c565b60008060008061051f85610fd9565b6040516318d7d3ef60e11b815290915030906331afa7de90610545908490600401612566565b602060405180830381865afa92505050801561057e575060408051601f3d908101601f1916820190925261057b918101906125a5565b60015b61067c573d8080156105ac576040519150601f19603f3d011682016040523d82523d6000602084013e6105b1565b606091505b5060006105bd826110cc565b909650945090506327f5146f60e01b6001600160e01b03198216016105e55760019550610675565b6357761ca160e11b6001600160e01b03198216016106065760029550610675565b631627ab1760e31b6001600160e01b03198216016106275760039550610675565b6305d6c00360e41b6001600160e01b03198216016106485760049550610675565b631515fcbb60e01b6001600160e01b03198216016106695760059550610675565b60069550600094508493505b505061068e565b50600093508392508291506106909050565b505b9193909250565b600046826001600160401b0316036106d257604051636b0dc00560e11b81526001600160401b03831660048201526024015b60405180910390fd5b506001600160401b031660009081526003602052604090205490565b6000806106fb8484611112565b905061070a8160a001516111b3565b506000848460405161071d9291906125c7565b604051809103902090506107318282611223565b6001925050505b92915050565b600046826001600160401b03160361077457604051636b0dc00560e11b81526001600160401b03831660048201526024016106c9565b506001600160401b038116600090815260036020526040902054806001600160a01b03811681146107bb5760405163ec3822b160e01b8152600481018290526024016106c9565b50919050565b6107c9611361565b6001600160a01b0381166107f057604051633bb893a160e01b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527ffa842b3692f81757c2420f55af6ab68a0a16f77c893dd8e2011c327d6c19ed49906020015b60405180910390a150565b60408051808201909152600080825260208201526001600160a01b0389166108748b828b8b8b8b8b8b8b61138e565b9b9a5050505050505050505050565b60408051808201909152600080825260208201526108a88a8a8a8a8a8a8a8a8a61138e565b9a9950505050505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526060826001600160a01b03163b60000361091257604051630a293ffd60e41b81526001600160a01b03841660048201526024016106c9565b60408051600481526024810182526020810180516001600160e01b031663287bc05760e01b179052905160009182916001600160a01b03871691610955916125d7565b600060405180830381855afa9150503d8060008114610990576040519150601f19603f3d011682016040523d82523d6000602084013e610995565b606091505b50915091508115806109a657508051155b156109cf57604051630a293ffd60e41b81526001600160a01b03861660048201526024016106c9565b6060818060200190518101906109e591906125f3565b945090506109f2816117e6565b94508351600003610a5e576040805160018082528183019092529060208083019080368337505060025482519296506001600160a01b031691869150600090610a3d57610a3d612707565b60200260200101906001600160a01b031690816001600160a01b0316815250505b845160ff16600003610a7a57610a74845161185d565b60ff1685525b505050915091565b610a8a611361565b610a94600061188f565b565b6000610aa28383611112565b905060008383604051610ab69291906125c7565b60405180910390209050610aca8282611223565b600081815260046020526040812080546001600160a01b0319163317905560a0830151610af6906111b3565b905080602001513414610b2b5760208101516040516366f7ba5d60e01b815234600482015260248101919091526044016106c9565b8051861015610b3957805195505b60005a9050868111610b685760405163176b11a760e21b815260048101829052602481018890526044016106c9565b60808401516001600160a01b0316630421a1f088348760000151886060015189604001518a60c001516040518763ffffffff1660e01b8152600401610bb0949392919061271d565b6000604051808303818589803b158015610bc957600080fd5b5088f1158015610bdd573d6000803e3d6000fd5b50505050505083608001518460600151847f6bca840947c9cad2cc8a66e663c1ca33d73c416b8a8d7e74345a1106b74a81fb87604001518860000151604051610c3c9291906001600160401b0392831681529116602082015260400190565b60405180910390a450505050505050565b6000818152600460205260408120546001600160a01b031680610c865760405163e99eb48d60e01b8152600481018490526024016106c9565b60008382604051602001610cad9291909182526001600160a01b0316602082015260400190565b60408051808303601f19018152908290528051602082012063156c638360e11b8352600483015291507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632ad8c706906024016020604051808303816000875af1158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190612759565b6040516001600160401b03821681529093506001600160a01b0383169085907fab644d167c2c65a7ca17d6920e7681356b90f09279e2b7dc4c714b826ea4fbcc9060200160405180910390a35050919050565b610da8611361565b6001600160a01b038116610dcf57604051633184f16960e21b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527fa42a6dc10e430cab5d4ba037ea6d7eee30240c6b6d7dd5b12a3d2acf41e7264f9060200161083a565b6000610e28886118df565b506001600160a01b038716610e505760405163146fd3c560e21b815260040160405180910390fd5b610e8f84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506111b392505050565b5060405163b8ba4ba160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b8ba4ba190610ee0908b908a908a906004016127bf565b602060405180830381865afa158015610efd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2191906127eb565b90506000610f2f8484611960565b604051634b7ed26d60e11b81529091506001600160a01b038916906396fda4da90610f64908c9085908a908a9060040161282d565b602060405180830381865afa158015610f81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa591906127eb565b610faf9083612856565b9998505050505050505050565b6040805180820190915260008082526020820152610738826111b3565b60606107386001610fe984611987565b611a0b565b610ff6611361565b6001600160a01b03811661102057604051631e4fbdf760e01b8152600060048201526024016106c9565b6110298161188f565b50565b611034611361565b6001600160401b038216600081815260036020908152604091829020849055815192835282018390527ffdc2498138df0de25c8fc9bd75bb8e856dac69aaf28d3dd5e0fc48e5e9f6e93f910160405180910390a15050565b60006004600084846040516110a29291906125c7565b60408051918290039091208252602082019290925201600020546001600160a01b03169392505050565b600080600060048451106110ec5760208401516001600160e01b03191692505b60248451106110fd57602484015191505b60448451106106905750604492909201519092565b61111a611ecf565b60006111268484611a37565b905061ffff811660011461115a576040516316d8807d60e11b815261ffff82166004820152600160248201526044016106c9565b61116c6111678585611a68565b611aaa565b91504682602001516001600160401b0316146111ac57602082015160405163eaea034560e01b81526001600160401b0390911660048201526024016106c9565b5092915050565b604080518082019091526000808252602082015260006111d283611b0b565b9050600161ffff8216101561120057604051632b346f3760e01b815261ffff821660048201526024016106c9565b61120983611b3d565b80602001905181019061121c9190612877565b9392505050565b600061123283600001516118df565b6000838152600460205260409020549091506001600160a01b03161561126e5760405163d80aeb9160e01b8152600481018390526024016106c9565b604080516060808201835285516001600160401b039081168352868401511660208084019190915283518082018690528085018790528451808203860181529201845281519101209181019190915260808401516000806112ce836108b6565b9150915060006112dd83611be6565b90506112e98186611c28565b60006001600160a01b03821615611304578360200151611307565b60005b65ffffffffffff169050600061131e848884611cfe565b855190915060ff16811015611355578451604051632889e35f60e11b81526004810183905260ff90911660248201526044016106c9565b50505050505050505050565b6000546001600160a01b03163314610a945760405163118cdaa760e01b81523360048201526024016106c9565b60408051808201909152600080825260208201526113ab8a6118df565b5060008990036113ce576040516330014e4760e21b815260040160405180910390fd5b6001600160a01b0388166113f55760405163146fd3c560e21b815260040160405180910390fd5b61143485858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506111b392505050565b5060405163b8ba4ba160e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b8ba4ba190611488908e908c908c906004016127bf565b602060405180830381865afa1580156114a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c991906127eb565b9050803410156114f55760405163457bf1e160e11b8152346004820152602481018290526044016106c9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f338140e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611553573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115779190612759565b82602001906001600160401b031690816001600160401b0316815250506000611611338d8d86602001518b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8f018190048102820181019092528d815292508d91508c9081908401838280828437600092019190915250611e2092505050565b905061161c81610fd9565b8051906020012083600001818152505060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635fecf58d84846020015187600001518e8e6040518663ffffffff1660e01b815260040161168994939291906128c5565b60206040518083038185885af11580156116a7573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906116cc9190612759565b905083602001516001600160401b0316816001600160401b0316146116f3576116f36128ee565b50602081015134839003906001600160a01b038c16906358efb47d90839061171b8b8a611960565b88516040516001600160e01b031960e087901b168152611744939291908f908f90600401612904565b6000604051808303818588803b15801561175d57600080fd5b505af1158015611771573d6000803e3d6000fd5b50505050508160800151826060015185600001517f4085591259df9982b703db65d112e8413b755dc4e74984fc5132fe4220fede268760200151866020015188878960a001518a60c001516040516117ce9695949392919061293e565b60405180910390a45050509998505050505050505050565b60408051608081018252600080825260208201819052918101829052606081018290529061181383611b0b565b9050600161ffff8216101561184157604051635b72a46360e11b815261ffff821660048201526024016106c9565b61184a83611b3d565b80602001905181019061121c9190612999565b600060ff82111561188b576040516306dfcc6560e41b815260086004820152602481018390526044016106c9565b5090565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600046826001600160401b03160361191557604051636b0dc00560e11b81526001600160401b03831660048201526024016106c9565b506001600160401b0381166000908152600360205260408120549081900361195b57604051632e3a383760e21b81526001600160401b03831660048201526024016106c9565b919050565b6000601f19601f830116601f19601f85011661197d9060e2612856565b61121c9190612856565b805160208201516040808401516060936001600160401b039091169290911b6fffffffffffffffff00000000000000001660809190911b67ffffffffffffffff60801b161717826060015183608001518460a001518560c001516040516020016119f5959493929190612a24565b6040516020818303038152906040529050919050565b60608282604051602001611a20929190612a67565b604051602081830303815290604052905092915050565b60006002821015611a5f578282604051635840c5b160e11b81526004016106c9929190612a97565b50503560f01c90565b3660006002831015611a91578383604051635840c5b160e11b81526004016106c9929190612a97565b611a9e8360028187612aab565b915091505b9250929050565b611ab2611ecf565b6000611ac083850185612ad5565b60c087015260a0860152608085015260608401529050611ae981608081901c91604082901c9190565b6001600160401b03908116604086015290811660208501521682525092915050565b6000600282511015611b325781604051635840c5b160e11b81526004016106c99190612566565b506020015160f01c90565b6060600282511015611b645781604051635840c5b160e11b81526004016106c99190612566565b815160011901806001600160401b03811115611b8257611b82611f0d565b6040519080825280601f01601f191660200182016040528015611bac576020820181803683370190505b50915060008160208401836022870160045afa905080611bdf5760405163080f227d60e11b815260040160405180910390fd5b5050919050565b604081015160009060ff16611bfd57506000919050565b600160ff16826040015160ff1603611c205750506001546001600160a01b031690565b506060015190565b6001600160a01b03821615611cfa576040516387c59c6f60e01b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906387c59c6f90611c889086908690600401612b55565b602060405180830381865afa158015611ca5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cc991906127eb565b90506000198103611cf8576040516309d854e960e31b81526001600160a01b03841660048201526024016106c9565b505b5050565b6000805b8451811015611e18576000858281518110611d1f57611d1f612707565b6020026020010151905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166387c59c6f83886040518363ffffffff1660e01b8152600401611d79929190612b55565b602060405180830381865afa158015611d96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dba91906127eb565b905080611dc8575050611e10565b6000198103611df5576040516309d854e960e31b81526001600160a01b03831660048201526024016106c9565b42611e008683612856565b1015611e0d578360010193505b50505b600101611d02565b509392505050565b611e28611ecf565b6040518060e00160405280611e3c46611e99565b6001600160401b03168152602001876001600160401b03168152602001856001600160401b03168152602001611e78896001600160a01b031690565b81526020018681526020018481526020018381525090509695505050505050565b60006001600160401b0382111561188b57604080516306dfcc6560e41b81526004810191909152602481018390526044016106c9565b6040805160e0810182526000808252602082018190529181018290526060808201839052608082019290925260a0810182905260c081019190915290565b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b0381118282101715611f4557611f45611f0d565b60405290565b604051601f8201601f191681016001600160401b0381118282101715611f7357611f73611f0d565b604052919050565b6001600160401b038116811461102957600080fd5b803561195b81611f7b565b60006001600160401b03821115611fb457611fb4611f0d565b50601f01601f191660200190565b600082601f830112611fd357600080fd5b8135611fe6611fe182611f9b565b611f4b565b818152846020838601011115611ffb57600080fd5b816020850160208301376000918101602001919091529392505050565b60006020828403121561202a57600080fd5b81356001600160401b038082111561204157600080fd5b9083019060e0828603121561205557600080fd5b61205d611f23565b61206683611f90565b815261207460208401611f90565b602082015261208560408401611f90565b6040820152606083013560608201526080830135608082015260a0830135828111156120b057600080fd5b6120bc87828601611fc2565b60a08301525060c0830135828111156120d457600080fd5b6120e087828601611fc2565b60c08301525095945050505050565b606081016007851061211157634e487b7160e01b600052602160045260246000fd5b938152602081019290925260409091015290565b60006020828403121561213757600080fd5b813561121c81611f7b565b60008083601f84011261215457600080fd5b5081356001600160401b0381111561216b57600080fd5b602083019150836020828501011115611aa357600080fd5b6000806020838503121561219657600080fd5b82356001600160401b038111156121ac57600080fd5b6121b885828601612142565b90969095509350505050565b6001600160a01b038116811461102957600080fd5b6000602082840312156121eb57600080fd5b813561121c816121c4565b60008083601f84011261220857600080fd5b5081356001600160401b0381111561221f57600080fd5b6020830191508360208260051b8501011115611aa357600080fd5b600080600080600080600080600060c08a8c03121561225857600080fd5b893561226381611f7b565b985060208a0135612273816121c4565b975060408a0135612283816121c4565b965060608a01356001600160401b038082111561229f57600080fd5b6122ab8d838e016121f6565b909850965060808c01359150808211156122c457600080fd5b6122d08d838e01612142565b909650945060a08c01359150808211156122e957600080fd5b506122f68c828d01612142565b915080935050809150509295985092959850929598565b600080600080600080600080600060c08a8c03121561232b57600080fd5b893561233681611f7b565b985060208a0135975060408a0135612283816121c4565b600060a0820160ff8551168352602065ffffffffffff602087015116602085015260ff6040870151166040850152606086015160018060a01b03808216606087015260a06080870152839150865180855260c08701925060208801945060005b818110156123cb5785518316845294840194928401926001016123ad565b509198975050505050505050565b6000806000604084860312156123ee57600080fd5b8335925060208401356001600160401b0381111561240b57600080fd5b61241786828701612142565b9497909650939450505050565b60006020828403121561243657600080fd5b5035919050565b600080600080600080600060a0888a03121561245857600080fd5b873561246381611f7b565b96506020880135612473816121c4565b955060408801356001600160401b038082111561248f57600080fd5b61249b8b838c016121f6565b909750955060608a01359150808211156124b457600080fd5b506124c18a828b01612142565b989b979a50959894979596608090950135949350505050565b6000602082840312156124ec57600080fd5b81356001600160401b0381111561250257600080fd5b61250e84828501611fc2565b949350505050565b60005b83811015612531578181015183820152602001612519565b50506000910152565b60008151808452612552816020860160208601612516565b601f01601f19169290920160200192915050565b60208152600061121c602083018461253a565b6000806040838503121561258c57600080fd5b823561259781611f7b565b946020939093013593505050565b6000602082840312156125b757600080fd5b8151801515811461121c57600080fd5b8183823760009101908152919050565b600082516125e9818460208701612516565b9190910192915050565b6000806040838503121561260657600080fd5b82516001600160401b038082111561261d57600080fd5b818501915085601f83011261263157600080fd5b81516020612641611fe183611f9b565b828152888284870101111561265557600080fd5b61266483838301848801612516565b8782015190965093508284111561267a57600080fd5b838701935087601f85011261268e57600080fd5b83519150828211156126a2576126a2611f0d565b8160051b92506126b3818401611f4b565b82815292840181019281810190898511156126cd57600080fd5b948201945b848610156126f757855193506126e7846121c4565b83825294820194908201906126d2565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006001600160401b0380871683528560208401528085166040840152506080606083015261274f608083018461253a565b9695505050505050565b60006020828403121561276b57600080fd5b815161121c81611f7b565b8183526000602080850194508260005b858110156127b4578135612799816121c4565b6001600160a01b031687529582019590820190600101612786565b509495945050505050565b6001600160401b03841681526040602082015260006127e2604083018486612776565b95945050505050565b6000602082840312156127fd57600080fd5b5051919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160401b038516815283602082015260606040820152600061274f606083018486612804565b8082018082111561073857634e487b7160e01b600052601160045260246000fd5b60006040828403121561288957600080fd5b604051604081018181106001600160401b03821117156128ab576128ab611f0d565b604052825181526020928301519281019290925250919050565b6001600160401b038516815283602082015260606040820152600061274f606083018486612776565b634e487b7160e01b600052600160045260246000fd5b6001600160401b0386168152846020820152836040820152608060608201526000612933608083018486612804565b979650505050505050565b60006001600160401b03808916835280881660208401525085604083015284606083015260c0608083015261297660c083018561253a565b82810360a0840152610faf818561253a565b805160ff8116811461195b57600080fd5b6000608082840312156129ab57600080fd5b604051608081018181106001600160401b03821117156129cd576129cd611f0d565b6040526129d983612988565b8152602083015165ffffffffffff811681146129f457600080fd5b6020820152612a0560408401612988565b60408201526060830151612a18816121c4565b60608201529392505050565b85815284602082015283604082015260a060608201526000612a4960a083018561253a565b8281036080840152612a5b818561253a565b98975050505050505050565b61ffff60f01b8360f01b16815260008251612a89816002850160208701612516565b919091016002019392505050565b60208152600061250e602083018486612804565b60008085851115612abb57600080fd5b83861115612ac857600080fd5b5050820193919092039150565b600080600080600060a08688031215612aed57600080fd5b85359450602086013593506040860135925060608601356001600160401b0380821115612b1957600080fd5b612b2589838a01611fc2565b93506080880135915080821115612b3b57600080fd5b50612b4888828901611fc2565b9150509295509295909350565b6001600160a01b0392909216825280516001600160401b0390811660208085019190915282015116604080840191909152015160608201526080019056fea264697066735822122075b5d045844692116640851ae4ef6651244619dbe89fbafc50cdf3322fcd0c8b64736f6c634300081800330000000000000000000000002def303ea27a3674bb3a5d017e60b2ef43312a11000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4
Deployed Bytecode
0x60806040526004361061014b5760003560e01c80638da5cb5b116100b6578063e4c612471161006f578063e4c6124714610419578063f06c79771461044d578063f1a61fac1461047a578063f2fde38b146104b0578063f3c66e2b146104d0578063f92a79ff146104f057600080fd5b80638da5cb5b1461032857806390e810771461034657806394bf49f41461037e578063cbb3c6311461039e578063d5e788a0146103be578063e4344069146103f957600080fd5b80633f34448e116101085780633f34448e14610260578063547efb8414610297578063695fd54f146102aa578063715018a6146102d85780637813cd52146102ed57806380efe7771461031557600080fd5b80630a24bb93146101505780632a20521e146101885780632e568739146101c057806331afa7de146101ee57806335c4a1911461021e5780633d677ed01461023e575b600080fd5b34801561015c57600080fd5b5061017061016b366004612018565b610510565b60405161017f939291906120ef565b60405180910390f35b34801561019457600080fd5b506001546101a8906001600160a01b031681565b6040516001600160a01b03909116815260200161017f565b3480156101cc57600080fd5b506101e06101db366004612125565b610697565b60405190815260200161017f565b3480156101fa57600080fd5b5061020e610209366004612183565b6106ee565b604051901515815260200161017f565b34801561022a57600080fd5b506101a8610239366004612125565b61073e565b34801561024a57600080fd5b5061025e6102593660046121d9565b6107c1565b005b61027361026e36600461223a565b610845565b60408051825181526020928301516001600160401b0316928101929092520161017f565b6102736102a536600461230d565b610883565b3480156102b657600080fd5b506102ca6102c53660046121d9565b6108b6565b60405161017f92919061234d565b3480156102e457600080fd5b5061025e610a82565b3480156102f957600080fd5b50610302600181565b60405161ffff909116815260200161017f565b61025e6103233660046123d9565b610a96565b34801561033457600080fd5b506000546001600160a01b03166101a8565b34801561035257600080fd5b50610366610361366004612424565b610c4d565b6040516001600160401b03909116815260200161017f565b34801561038a57600080fd5b5061025e6103993660046121d9565b610da0565b3480156103aa57600080fd5b506101e06103b936600461243d565b610e1d565b3480156103ca57600080fd5b506103de6103d93660046124da565b610fbc565b6040805182518152602092830151928101929092520161017f565b34801561040557600080fd5b506002546101a8906001600160a01b031681565b34801561042557600080fd5b506101a87f0000000000000000000000002def303ea27a3674bb3a5d017e60b2ef43312a1181565b34801561045957600080fd5b5061046d610468366004612018565b610fd9565b60405161017f9190612566565b34801561048657600080fd5b506101a8610495366004612424565b6000908152600460205260409020546001600160a01b031690565b3480156104bc57600080fd5b5061025e6104cb3660046121d9565b610fee565b3480156104dc57600080fd5b5061025e6104eb366004612579565b61102c565b3480156104fc57600080fd5b506101a861050b366004612183565b61108c565b60008060008061051f85610fd9565b6040516318d7d3ef60e11b815290915030906331afa7de90610545908490600401612566565b602060405180830381865afa92505050801561057e575060408051601f3d908101601f1916820190925261057b918101906125a5565b60015b61067c573d8080156105ac576040519150601f19603f3d011682016040523d82523d6000602084013e6105b1565b606091505b5060006105bd826110cc565b909650945090506327f5146f60e01b6001600160e01b03198216016105e55760019550610675565b6357761ca160e11b6001600160e01b03198216016106065760029550610675565b631627ab1760e31b6001600160e01b03198216016106275760039550610675565b6305d6c00360e41b6001600160e01b03198216016106485760049550610675565b631515fcbb60e01b6001600160e01b03198216016106695760059550610675565b60069550600094508493505b505061068e565b50600093508392508291506106909050565b505b9193909250565b600046826001600160401b0316036106d257604051636b0dc00560e11b81526001600160401b03831660048201526024015b60405180910390fd5b506001600160401b031660009081526003602052604090205490565b6000806106fb8484611112565b905061070a8160a001516111b3565b506000848460405161071d9291906125c7565b604051809103902090506107318282611223565b6001925050505b92915050565b600046826001600160401b03160361077457604051636b0dc00560e11b81526001600160401b03831660048201526024016106c9565b506001600160401b038116600090815260036020526040902054806001600160a01b03811681146107bb5760405163ec3822b160e01b8152600481018290526024016106c9565b50919050565b6107c9611361565b6001600160a01b0381166107f057604051633bb893a160e01b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527ffa842b3692f81757c2420f55af6ab68a0a16f77c893dd8e2011c327d6c19ed49906020015b60405180910390a150565b60408051808201909152600080825260208201526001600160a01b0389166108748b828b8b8b8b8b8b8b61138e565b9b9a5050505050505050505050565b60408051808201909152600080825260208201526108a88a8a8a8a8a8a8a8a8a61138e565b9a9950505050505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526060826001600160a01b03163b60000361091257604051630a293ffd60e41b81526001600160a01b03841660048201526024016106c9565b60408051600481526024810182526020810180516001600160e01b031663287bc05760e01b179052905160009182916001600160a01b03871691610955916125d7565b600060405180830381855afa9150503d8060008114610990576040519150601f19603f3d011682016040523d82523d6000602084013e610995565b606091505b50915091508115806109a657508051155b156109cf57604051630a293ffd60e41b81526001600160a01b03861660048201526024016106c9565b6060818060200190518101906109e591906125f3565b945090506109f2816117e6565b94508351600003610a5e576040805160018082528183019092529060208083019080368337505060025482519296506001600160a01b031691869150600090610a3d57610a3d612707565b60200260200101906001600160a01b031690816001600160a01b0316815250505b845160ff16600003610a7a57610a74845161185d565b60ff1685525b505050915091565b610a8a611361565b610a94600061188f565b565b6000610aa28383611112565b905060008383604051610ab69291906125c7565b60405180910390209050610aca8282611223565b600081815260046020526040812080546001600160a01b0319163317905560a0830151610af6906111b3565b905080602001513414610b2b5760208101516040516366f7ba5d60e01b815234600482015260248101919091526044016106c9565b8051861015610b3957805195505b60005a9050868111610b685760405163176b11a760e21b815260048101829052602481018890526044016106c9565b60808401516001600160a01b0316630421a1f088348760000151886060015189604001518a60c001516040518763ffffffff1660e01b8152600401610bb0949392919061271d565b6000604051808303818589803b158015610bc957600080fd5b5088f1158015610bdd573d6000803e3d6000fd5b50505050505083608001518460600151847f6bca840947c9cad2cc8a66e663c1ca33d73c416b8a8d7e74345a1106b74a81fb87604001518860000151604051610c3c9291906001600160401b0392831681529116602082015260400190565b60405180910390a450505050505050565b6000818152600460205260408120546001600160a01b031680610c865760405163e99eb48d60e01b8152600481018490526024016106c9565b60008382604051602001610cad9291909182526001600160a01b0316602082015260400190565b60408051808303601f19018152908290528051602082012063156c638360e11b8352600483015291507f0000000000000000000000002def303ea27a3674bb3a5d017e60b2ef43312a116001600160a01b031690632ad8c706906024016020604051808303816000875af1158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190612759565b6040516001600160401b03821681529093506001600160a01b0383169085907fab644d167c2c65a7ca17d6920e7681356b90f09279e2b7dc4c714b826ea4fbcc9060200160405180910390a35050919050565b610da8611361565b6001600160a01b038116610dcf57604051633184f16960e21b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527fa42a6dc10e430cab5d4ba037ea6d7eee30240c6b6d7dd5b12a3d2acf41e7264f9060200161083a565b6000610e28886118df565b506001600160a01b038716610e505760405163146fd3c560e21b815260040160405180910390fd5b610e8f84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506111b392505050565b5060405163b8ba4ba160e01b81526001600160a01b037f0000000000000000000000002def303ea27a3674bb3a5d017e60b2ef43312a11169063b8ba4ba190610ee0908b908a908a906004016127bf565b602060405180830381865afa158015610efd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2191906127eb565b90506000610f2f8484611960565b604051634b7ed26d60e11b81529091506001600160a01b038916906396fda4da90610f64908c9085908a908a9060040161282d565b602060405180830381865afa158015610f81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa591906127eb565b610faf9083612856565b9998505050505050505050565b6040805180820190915260008082526020820152610738826111b3565b60606107386001610fe984611987565b611a0b565b610ff6611361565b6001600160a01b03811661102057604051631e4fbdf760e01b8152600060048201526024016106c9565b6110298161188f565b50565b611034611361565b6001600160401b038216600081815260036020908152604091829020849055815192835282018390527ffdc2498138df0de25c8fc9bd75bb8e856dac69aaf28d3dd5e0fc48e5e9f6e93f910160405180910390a15050565b60006004600084846040516110a29291906125c7565b60408051918290039091208252602082019290925201600020546001600160a01b03169392505050565b600080600060048451106110ec5760208401516001600160e01b03191692505b60248451106110fd57602484015191505b60448451106106905750604492909201519092565b61111a611ecf565b60006111268484611a37565b905061ffff811660011461115a576040516316d8807d60e11b815261ffff82166004820152600160248201526044016106c9565b61116c6111678585611a68565b611aaa565b91504682602001516001600160401b0316146111ac57602082015160405163eaea034560e01b81526001600160401b0390911660048201526024016106c9565b5092915050565b604080518082019091526000808252602082015260006111d283611b0b565b9050600161ffff8216101561120057604051632b346f3760e01b815261ffff821660048201526024016106c9565b61120983611b3d565b80602001905181019061121c9190612877565b9392505050565b600061123283600001516118df565b6000838152600460205260409020549091506001600160a01b03161561126e5760405163d80aeb9160e01b8152600481018390526024016106c9565b604080516060808201835285516001600160401b039081168352868401511660208084019190915283518082018690528085018790528451808203860181529201845281519101209181019190915260808401516000806112ce836108b6565b9150915060006112dd83611be6565b90506112e98186611c28565b60006001600160a01b03821615611304578360200151611307565b60005b65ffffffffffff169050600061131e848884611cfe565b855190915060ff16811015611355578451604051632889e35f60e11b81526004810183905260ff90911660248201526044016106c9565b50505050505050505050565b6000546001600160a01b03163314610a945760405163118cdaa760e01b81523360048201526024016106c9565b60408051808201909152600080825260208201526113ab8a6118df565b5060008990036113ce576040516330014e4760e21b815260040160405180910390fd5b6001600160a01b0388166113f55760405163146fd3c560e21b815260040160405180910390fd5b61143485858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506111b392505050565b5060405163b8ba4ba160e01b81526000906001600160a01b037f0000000000000000000000002def303ea27a3674bb3a5d017e60b2ef43312a11169063b8ba4ba190611488908e908c908c906004016127bf565b602060405180830381865afa1580156114a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c991906127eb565b9050803410156114f55760405163457bf1e160e11b8152346004820152602481018290526044016106c9565b7f0000000000000000000000002def303ea27a3674bb3a5d017e60b2ef43312a116001600160a01b031663f338140e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611553573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115779190612759565b82602001906001600160401b031690816001600160401b0316815250506000611611338d8d86602001518b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8f018190048102820181019092528d815292508d91508c9081908401838280828437600092019190915250611e2092505050565b905061161c81610fd9565b8051906020012083600001818152505060007f0000000000000000000000002def303ea27a3674bb3a5d017e60b2ef43312a116001600160a01b0316635fecf58d84846020015187600001518e8e6040518663ffffffff1660e01b815260040161168994939291906128c5565b60206040518083038185885af11580156116a7573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906116cc9190612759565b905083602001516001600160401b0316816001600160401b0316146116f3576116f36128ee565b50602081015134839003906001600160a01b038c16906358efb47d90839061171b8b8a611960565b88516040516001600160e01b031960e087901b168152611744939291908f908f90600401612904565b6000604051808303818588803b15801561175d57600080fd5b505af1158015611771573d6000803e3d6000fd5b50505050508160800151826060015185600001517f4085591259df9982b703db65d112e8413b755dc4e74984fc5132fe4220fede268760200151866020015188878960a001518a60c001516040516117ce9695949392919061293e565b60405180910390a45050509998505050505050505050565b60408051608081018252600080825260208201819052918101829052606081018290529061181383611b0b565b9050600161ffff8216101561184157604051635b72a46360e11b815261ffff821660048201526024016106c9565b61184a83611b3d565b80602001905181019061121c9190612999565b600060ff82111561188b576040516306dfcc6560e41b815260086004820152602481018390526044016106c9565b5090565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600046826001600160401b03160361191557604051636b0dc00560e11b81526001600160401b03831660048201526024016106c9565b506001600160401b0381166000908152600360205260408120549081900361195b57604051632e3a383760e21b81526001600160401b03831660048201526024016106c9565b919050565b6000601f19601f830116601f19601f85011661197d9060e2612856565b61121c9190612856565b805160208201516040808401516060936001600160401b039091169290911b6fffffffffffffffff00000000000000001660809190911b67ffffffffffffffff60801b161717826060015183608001518460a001518560c001516040516020016119f5959493929190612a24565b6040516020818303038152906040529050919050565b60608282604051602001611a20929190612a67565b604051602081830303815290604052905092915050565b60006002821015611a5f578282604051635840c5b160e11b81526004016106c9929190612a97565b50503560f01c90565b3660006002831015611a91578383604051635840c5b160e11b81526004016106c9929190612a97565b611a9e8360028187612aab565b915091505b9250929050565b611ab2611ecf565b6000611ac083850185612ad5565b60c087015260a0860152608085015260608401529050611ae981608081901c91604082901c9190565b6001600160401b03908116604086015290811660208501521682525092915050565b6000600282511015611b325781604051635840c5b160e11b81526004016106c99190612566565b506020015160f01c90565b6060600282511015611b645781604051635840c5b160e11b81526004016106c99190612566565b815160011901806001600160401b03811115611b8257611b82611f0d565b6040519080825280601f01601f191660200182016040528015611bac576020820181803683370190505b50915060008160208401836022870160045afa905080611bdf5760405163080f227d60e11b815260040160405180910390fd5b5050919050565b604081015160009060ff16611bfd57506000919050565b600160ff16826040015160ff1603611c205750506001546001600160a01b031690565b506060015190565b6001600160a01b03821615611cfa576040516387c59c6f60e01b81526000906001600160a01b037f0000000000000000000000002def303ea27a3674bb3a5d017e60b2ef43312a1116906387c59c6f90611c889086908690600401612b55565b602060405180830381865afa158015611ca5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cc991906127eb565b90506000198103611cf8576040516309d854e960e31b81526001600160a01b03841660048201526024016106c9565b505b5050565b6000805b8451811015611e18576000858281518110611d1f57611d1f612707565b6020026020010151905060007f0000000000000000000000002def303ea27a3674bb3a5d017e60b2ef43312a116001600160a01b03166387c59c6f83886040518363ffffffff1660e01b8152600401611d79929190612b55565b602060405180830381865afa158015611d96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dba91906127eb565b905080611dc8575050611e10565b6000198103611df5576040516309d854e960e31b81526001600160a01b03831660048201526024016106c9565b42611e008683612856565b1015611e0d578360010193505b50505b600101611d02565b509392505050565b611e28611ecf565b6040518060e00160405280611e3c46611e99565b6001600160401b03168152602001876001600160401b03168152602001856001600160401b03168152602001611e78896001600160a01b031690565b81526020018681526020018481526020018381525090509695505050505050565b60006001600160401b0382111561188b57604080516306dfcc6560e41b81526004810191909152602481018390526044016106c9565b6040805160e0810182526000808252602082018190529181018290526060808201839052608082019290925260a0810182905260c081019190915290565b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b0381118282101715611f4557611f45611f0d565b60405290565b604051601f8201601f191681016001600160401b0381118282101715611f7357611f73611f0d565b604052919050565b6001600160401b038116811461102957600080fd5b803561195b81611f7b565b60006001600160401b03821115611fb457611fb4611f0d565b50601f01601f191660200190565b600082601f830112611fd357600080fd5b8135611fe6611fe182611f9b565b611f4b565b818152846020838601011115611ffb57600080fd5b816020850160208301376000918101602001919091529392505050565b60006020828403121561202a57600080fd5b81356001600160401b038082111561204157600080fd5b9083019060e0828603121561205557600080fd5b61205d611f23565b61206683611f90565b815261207460208401611f90565b602082015261208560408401611f90565b6040820152606083013560608201526080830135608082015260a0830135828111156120b057600080fd5b6120bc87828601611fc2565b60a08301525060c0830135828111156120d457600080fd5b6120e087828601611fc2565b60c08301525095945050505050565b606081016007851061211157634e487b7160e01b600052602160045260246000fd5b938152602081019290925260409091015290565b60006020828403121561213757600080fd5b813561121c81611f7b565b60008083601f84011261215457600080fd5b5081356001600160401b0381111561216b57600080fd5b602083019150836020828501011115611aa357600080fd5b6000806020838503121561219657600080fd5b82356001600160401b038111156121ac57600080fd5b6121b885828601612142565b90969095509350505050565b6001600160a01b038116811461102957600080fd5b6000602082840312156121eb57600080fd5b813561121c816121c4565b60008083601f84011261220857600080fd5b5081356001600160401b0381111561221f57600080fd5b6020830191508360208260051b8501011115611aa357600080fd5b600080600080600080600080600060c08a8c03121561225857600080fd5b893561226381611f7b565b985060208a0135612273816121c4565b975060408a0135612283816121c4565b965060608a01356001600160401b038082111561229f57600080fd5b6122ab8d838e016121f6565b909850965060808c01359150808211156122c457600080fd5b6122d08d838e01612142565b909650945060a08c01359150808211156122e957600080fd5b506122f68c828d01612142565b915080935050809150509295985092959850929598565b600080600080600080600080600060c08a8c03121561232b57600080fd5b893561233681611f7b565b985060208a0135975060408a0135612283816121c4565b600060a0820160ff8551168352602065ffffffffffff602087015116602085015260ff6040870151166040850152606086015160018060a01b03808216606087015260a06080870152839150865180855260c08701925060208801945060005b818110156123cb5785518316845294840194928401926001016123ad565b509198975050505050505050565b6000806000604084860312156123ee57600080fd5b8335925060208401356001600160401b0381111561240b57600080fd5b61241786828701612142565b9497909650939450505050565b60006020828403121561243657600080fd5b5035919050565b600080600080600080600060a0888a03121561245857600080fd5b873561246381611f7b565b96506020880135612473816121c4565b955060408801356001600160401b038082111561248f57600080fd5b61249b8b838c016121f6565b909750955060608a01359150808211156124b457600080fd5b506124c18a828b01612142565b989b979a50959894979596608090950135949350505050565b6000602082840312156124ec57600080fd5b81356001600160401b0381111561250257600080fd5b61250e84828501611fc2565b949350505050565b60005b83811015612531578181015183820152602001612519565b50506000910152565b60008151808452612552816020860160208601612516565b601f01601f19169290920160200192915050565b60208152600061121c602083018461253a565b6000806040838503121561258c57600080fd5b823561259781611f7b565b946020939093013593505050565b6000602082840312156125b757600080fd5b8151801515811461121c57600080fd5b8183823760009101908152919050565b600082516125e9818460208701612516565b9190910192915050565b6000806040838503121561260657600080fd5b82516001600160401b038082111561261d57600080fd5b818501915085601f83011261263157600080fd5b81516020612641611fe183611f9b565b828152888284870101111561265557600080fd5b61266483838301848801612516565b8782015190965093508284111561267a57600080fd5b838701935087601f85011261268e57600080fd5b83519150828211156126a2576126a2611f0d565b8160051b92506126b3818401611f4b565b82815292840181019281810190898511156126cd57600080fd5b948201945b848610156126f757855193506126e7846121c4565b83825294820194908201906126d2565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006001600160401b0380871683528560208401528085166040840152506080606083015261274f608083018461253a565b9695505050505050565b60006020828403121561276b57600080fd5b815161121c81611f7b565b8183526000602080850194508260005b858110156127b4578135612799816121c4565b6001600160a01b031687529582019590820190600101612786565b509495945050505050565b6001600160401b03841681526040602082015260006127e2604083018486612776565b95945050505050565b6000602082840312156127fd57600080fd5b5051919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160401b038516815283602082015260606040820152600061274f606083018486612804565b8082018082111561073857634e487b7160e01b600052601160045260246000fd5b60006040828403121561288957600080fd5b604051604081018181106001600160401b03821117156128ab576128ab611f0d565b604052825181526020928301519281019290925250919050565b6001600160401b038516815283602082015260606040820152600061274f606083018486612776565b634e487b7160e01b600052600160045260246000fd5b6001600160401b0386168152846020820152836040820152608060608201526000612933608083018486612804565b979650505050505050565b60006001600160401b03808916835280881660208401525085604083015284606083015260c0608083015261297660c083018561253a565b82810360a0840152610faf818561253a565b805160ff8116811461195b57600080fd5b6000608082840312156129ab57600080fd5b604051608081018181106001600160401b03821117156129cd576129cd611f0d565b6040526129d983612988565b8152602083015165ffffffffffff811681146129f457600080fd5b6020820152612a0560408401612988565b60408201526060830151612a18816121c4565b60608201529392505050565b85815284602082015283604082015260a060608201526000612a4960a083018561253a565b8281036080840152612a5b818561253a565b98975050505050505050565b61ffff60f01b8360f01b16815260008251612a89816002850160208701612516565b919091016002019392505050565b60208152600061250e602083018486612804565b60008085851115612abb57600080fd5b83861115612ac857600080fd5b5050820193919092039150565b600080600080600060a08688031215612aed57600080fd5b85359450602086013593506040860135925060608601356001600160401b0380821115612b1957600080fd5b612b2589838a01611fc2565b93506080880135915080821115612b3b57600080fd5b50612b4888828901611fc2565b9150509295509295909350565b6001600160a01b0392909216825280516001600160401b0390811660208085019190915282015116604080840191909152015160608201526080019056fea264697066735822122075b5d045844692116640851ae4ef6651244619dbe89fbafc50cdf3322fcd0c8b64736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000002def303ea27a3674bb3a5d017e60b2ef43312a11000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4
-----Decoded View---------------
Arg [0] : interchainDB (address): 0x2DeF303EA27a3674bb3a5d017e60B2Ef43312A11
Arg [1] : owner_ (address): 0xE7353BEdc72D29f99D6cA5CDE69F807cCE5d57e4
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000002def303ea27a3674bb3a5d017e60b2ef43312a11
Arg [1] : 000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.