Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Method | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|---|
Request Batch Ve... | 5711614 | 341 days ago | 0.0000001 ETH | ||||
Write Entry With... | 5711614 | 341 days ago | 0.0000001 ETH | ||||
Request Batch Ve... | 5711612 | 341 days ago | 0.0000001 ETH | ||||
Write Entry With... | 5711612 | 341 days ago | 0.0000001 ETH | ||||
Request Batch Ve... | 5711610 | 341 days ago | 0.0000001 ETH | ||||
Write Entry With... | 5711610 | 341 days ago | 0.0000001 ETH | ||||
Request Batch Ve... | 5711608 | 341 days ago | 0.0000001 ETH | ||||
Write Entry With... | 5711608 | 341 days ago | 0.0000001 ETH | ||||
Request Batch Ve... | 5711606 | 341 days ago | 0.0000001 ETH | ||||
Write Entry With... | 5711606 | 341 days ago | 0.0000001 ETH | ||||
Request Batch Ve... | 5711604 | 341 days ago | 0.0000001 ETH | ||||
Write Entry With... | 5711604 | 341 days ago | 0.0000001 ETH | ||||
Request Batch Ve... | 5711602 | 341 days ago | 0.0000001 ETH | ||||
Write Entry With... | 5711602 | 341 days ago | 0.0000001 ETH | ||||
Request Batch Ve... | 5711600 | 341 days ago | 0.0000001 ETH | ||||
Write Entry With... | 5711600 | 341 days ago | 0.0000001 ETH | ||||
Request Batch Ve... | 5711598 | 341 days ago | 0.0000001 ETH | ||||
Write Entry With... | 5711598 | 341 days ago | 0.0000001 ETH | ||||
Request Batch Ve... | 5711596 | 341 days ago | 0.0000001 ETH | ||||
Write Entry With... | 5711596 | 341 days ago | 0.0000001 ETH | ||||
Request Batch Ve... | 5711594 | 341 days ago | 0.0000001 ETH | ||||
Write Entry With... | 5711594 | 341 days ago | 0.0000001 ETH | ||||
Request Batch Ve... | 5711592 | 341 days ago | 0.0000001 ETH | ||||
Write Entry With... | 5711592 | 341 days ago | 0.0000001 ETH | ||||
Request Batch Ve... | 5711590 | 341 days ago | 0.0000001 ETH |
Loading...
Loading
Contract Name:
InterchainDB
Compiler Version
v0.8.20+commit.a1b79de6
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.20; import {InterchainDBEvents} from "./events/InterchainDBEvents.sol"; import {IInterchainDB} from "./interfaces/IInterchainDB.sol"; import {IInterchainModule} from "./interfaces/IInterchainModule.sol"; import {InterchainBatch, InterchainBatchLib} from "./libs/InterchainBatch.sol"; import {InterchainEntry, InterchainEntryLib} from "./libs/InterchainEntry.sol"; import {VersionedPayloadLib} from "./libs/VersionedPayload.sol"; contract InterchainDB is InterchainDBEvents, IInterchainDB { using VersionedPayloadLib for bytes; uint16 public constant DB_VERSION = 1; bytes32[] internal _entryValues; mapping(address module => mapping(bytes32 batchKey => RemoteBatch batch)) internal _remoteBatches; modifier onlyRemoteChainId(uint256 chainId) { if (chainId == block.chainid) { revert InterchainDB__SameChainId(block.chainid); } _; } // ═══════════════════════════════════════════════ WRITER-FACING ═══════════════════════════════════════════════════ /// @inheritdoc IInterchainDB function writeEntry(bytes32 dataHash) external returns (uint256 dbNonce, uint64 entryIndex) { InterchainEntry memory entry = _writeEntry(dataHash); (dbNonce, entryIndex) = (entry.dbNonce, entry.entryIndex); } /// @inheritdoc IInterchainDB function requestBatchVerification( uint256 dstChainId, uint256 dbNonce, address[] calldata srcModules ) external payable onlyRemoteChainId(dstChainId) { InterchainBatch memory batch = getBatch(dbNonce); _requestVerification(dstChainId, batch, srcModules); } /// @inheritdoc IInterchainDB function writeEntryWithVerification( uint256 dstChainId, bytes32 dataHash, address[] calldata srcModules ) external payable onlyRemoteChainId(dstChainId) returns (uint256 dbNonce, uint64 entryIndex) { InterchainEntry memory entry = _writeEntry(dataHash); (dbNonce, entryIndex) = (entry.dbNonce, entry.entryIndex); // In "no batching" mode: the batch root is the same as the entry value InterchainBatch memory batch = InterchainBatchLib.constructLocalBatch(dbNonce, entry.entryValue()); _requestVerification(dstChainId, batch, srcModules); } // ═══════════════════════════════════════════════ MODULE-FACING ═══════════════════════════════════════════════════ /// @inheritdoc IInterchainDB function verifyRemoteBatch(bytes calldata versionedBatch) external { uint16 dbVersion = versionedBatch.getVersion(); if (dbVersion != DB_VERSION) { revert InterchainDB__InvalidBatchVersion(dbVersion); } InterchainBatch memory batch = InterchainBatchLib.decodeBatch(versionedBatch.getPayload()); if (batch.srcChainId == block.chainid) { revert InterchainDB__SameChainId(batch.srcChainId); } bytes32 batchKey = InterchainBatchLib.batchKey(batch); RemoteBatch memory existingBatch = _remoteBatches[msg.sender][batchKey]; // Check if that's the first time module verifies the batch if (existingBatch.verifiedAt == 0) { _remoteBatches[msg.sender][batchKey] = RemoteBatch({verifiedAt: block.timestamp, batchRoot: batch.batchRoot}); emit InterchainBatchVerified(msg.sender, batch.srcChainId, batch.dbNonce, batch.batchRoot); } else { // If the module has already verified the batch, check that the batch root is the same if (existingBatch.batchRoot != batch.batchRoot) { revert InterchainDB__ConflictingBatches(msg.sender, existingBatch.batchRoot, batch); } // No-op if the batch root is the same } } // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════ /// @inheritdoc IInterchainDB function getBatchLeafsPaginated( uint256 dbNonce, uint64 start, uint64 end ) external view returns (bytes32[] memory leafs) { if (start != 0 || end != 1) { revert InterchainDB__InvalidEntryRange(dbNonce, start, end); } return getBatchLeafs(dbNonce); } /// @inheritdoc IInterchainDB function getEntryProof(uint256 dbNonce, uint64 entryIndex) external view returns (bytes32[] memory proof) { // In "no batching" mode: the batch root is the same as the entry value, hence the proof is empty _assertBatchFinalized(dbNonce); _assertEntryExists(dbNonce, entryIndex); return new bytes32[](0); } /// @inheritdoc IInterchainDB function getInterchainFee(uint256 dstChainId, address[] calldata srcModules) external view returns (uint256 fee) { (, fee) = _getModuleFees(dstChainId, getDBNonce(), srcModules); } /// @inheritdoc IInterchainDB function getNextEntryIndex() external view returns (uint256 dbNonce, uint64 entryIndex) { // In "no batching" mode: entry index is 0, batch size is 1 dbNonce = getDBNonce(); entryIndex = 0; } /// @inheritdoc IInterchainDB function checkVerification( address dstModule, InterchainEntry memory entry, bytes32[] calldata proof ) external view onlyRemoteChainId(entry.srcChainId) returns (uint256 moduleVerifiedAt) { // In "no batching" mode: the batch root is the same as the entry value, hence the proof is empty if (proof.length != 0) { // If proof is not empty, the batch root is not verified return 0; } // In "no batching" mode: entry index is 0, batch size is 1 if (entry.entryIndex != 0) { // If entry index is not 0, it does not belong to the batch return 0; } RemoteBatch memory remoteBatch = _remoteBatches[dstModule][InterchainEntryLib.batchKey(entry)]; bytes32 entryValue = InterchainEntryLib.entryValue(entry); // Check entry value against the batch root verified by the module return remoteBatch.batchRoot == entryValue ? remoteBatch.verifiedAt : 0; } /// @inheritdoc IInterchainDB function getBatchLeafs(uint256 dbNonce) public view returns (bytes32[] memory leafs) { // In "no batching" mode: the finalized batch size is 1 _assertBatchFinalized(dbNonce); leafs = new bytes32[](1); leafs[0] = getEntryValue(dbNonce, 0); } /// @inheritdoc IInterchainDB function getBatchSize(uint256 dbNonce) public view returns (uint64) { // In "no batching" mode: the finalized batch size is 1, the pending batch size is 0 uint256 pendingNonce = _assertBatchExists(dbNonce); return dbNonce < pendingNonce ? 1 : 0; } /// @inheritdoc IInterchainDB function getBatch(uint256 dbNonce) public view returns (InterchainBatch memory) { _assertBatchFinalized(dbNonce); // In "no batching" mode: the batch root is the same as the entry hash return InterchainBatchLib.constructLocalBatch(dbNonce, getEntryValue(dbNonce, 0)); } /// @inheritdoc IInterchainDB function getEntryValue(uint256 dbNonce, uint64 entryIndex) public view returns (bytes32) { _assertEntryExists(dbNonce, entryIndex); return _entryValues[dbNonce]; } /// @inheritdoc IInterchainDB function getDBNonce() public view returns (uint256) { return _entryValues.length; } // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════ /// @dev Write the entry to the database and emit the event. function _writeEntry(bytes32 dataHash) internal returns (InterchainEntry memory entry) { entry = InterchainEntryLib.constructLocalEntry({ dbNonce: getDBNonce(), entryIndex: 0, writer: msg.sender, dataHash: dataHash }); _entryValues.push(entry.entryValue()); emit InterchainEntryWritten(block.chainid, entry.dbNonce, entry.srcWriter, dataHash); } /// @dev Request the verification of the entry by the modules, and emit the event. /// Note: the validity of the passed entry and chain id being remote is enforced in the calling function. function _requestVerification( uint256 dstChainId, InterchainBatch memory batch, address[] calldata srcModules ) internal { (uint256[] memory fees, uint256 totalFee) = _getModuleFees(dstChainId, batch.dbNonce, srcModules); if (msg.value < totalFee) { revert InterchainDB__IncorrectFeeAmount(msg.value, totalFee); } else if (msg.value > totalFee) { // The exceeding amount goes to the first module fees[0] += msg.value - totalFee; } uint256 len = srcModules.length; bytes memory versionedBatch = VersionedPayloadLib.encodeVersionedPayload({ version: DB_VERSION, payload: InterchainBatchLib.encodeBatch(batch) }); for (uint256 i = 0; i < len; ++i) { IInterchainModule(srcModules[i]).requestBatchVerification{value: fees[i]}(dstChainId, versionedBatch); } emit InterchainBatchVerificationRequested(dstChainId, batch.dbNonce, batch.batchRoot, srcModules); } // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════ /// @dev Check that the batch with the given nonce exists and return the pending nonce. function _assertBatchExists(uint256 dbNonce) internal view returns (uint256 pendingNonce) { pendingNonce = getDBNonce(); if (dbNonce > pendingNonce) { revert InterchainDB__BatchDoesNotExist(dbNonce); } } /// @dev Check that the batch with the given nonce is finalized and return the pending nonce. function _assertBatchFinalized(uint256 dbNonce) internal view returns (uint256 pendingNonce) { pendingNonce = getDBNonce(); if (dbNonce >= pendingNonce) { revert InterchainDB__BatchNotFinalized(dbNonce); } } /// @dev Check that the entry index is within the batch size. Also checks that the batch exists. function _assertEntryExists(uint256 dbNonce, uint64 entryIndex) internal view { // This will revert if the batch does not exist uint64 batchSize = getBatchSize(dbNonce); if (entryIndex >= batchSize) { revert InterchainDB__EntryIndexOutOfRange(dbNonce, entryIndex, batchSize); } } /// @dev Get the verification fees for the modules function _getModuleFees( uint256 dstChainId, uint256 dbNonce, address[] calldata srcModules ) internal view returns (uint256[] memory fees, uint256 totalFee) { uint256 len = srcModules.length; if (len == 0) { revert InterchainDB__NoModulesSpecified(); } fees = new uint256[](len); for (uint256 i = 0; i < len; ++i) { fees[i] = IInterchainModule(srcModules[i]).getModuleFee(dstChainId, dbNonce); totalFee += fees[i]; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; abstract contract InterchainDBEvents { // TODO: figure out indexing event InterchainEntryWritten(uint256 srcChainId, uint256 dbNonce, bytes32 srcWriter, bytes32 dataHash); event InterchainBatchVerified(address module, uint256 srcChainId, uint256 dbNonce, bytes32 batchRoot); event InterchainBatchVerificationRequested( uint256 dstChainId, uint256 dbNonce, bytes32 batchRoot, address[] srcModules ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {InterchainEntry} from "../libs/InterchainEntry.sol"; import {InterchainBatch} from "../libs/InterchainBatch.sol"; interface IInterchainDB { /// @notice Struct representing a batch of entries from the remote Interchain DataBase, /// verified by the Interchain Module. /// @param verifiedAt The block timestamp at which the entry was verified by the module /// @param batchRoot The Merkle root of the batch struct RemoteBatch { uint256 verifiedAt; bytes32 batchRoot; } error InterchainDB__BatchDoesNotExist(uint256 dbNonce); error InterchainDB__BatchNotFinalized(uint256 dbNonce); error InterchainDB__ConflictingBatches(address module, bytes32 existingBatchRoot, InterchainBatch newBatch); error InterchainDB__EntryIndexOutOfRange(uint256 dbNonce, uint64 entryIndex, uint64 batchSize); error InterchainDB__IncorrectFeeAmount(uint256 actualFee, uint256 expectedFee); error InterchainDB__InvalidBatchVersion(uint16 version); error InterchainDB__InvalidEntryRange(uint256 dbNonce, uint64 start, uint64 end); error InterchainDB__NoModulesSpecified(); error InterchainDB__SameChainId(uint256 chainId); /// @notice Write data to the Interchain DataBase as a new entry in the current batch. /// Note: there are no guarantees that this entry will be available for reading on any of the remote chains. /// Use `requestBatchVerification` to ensure that the entry is available for reading on the destination chain. /// @param dataHash The hash of the data to be written to the Interchain DataBase as a new entry /// @return dbNonce The database nonce of the batch containing the written entry /// @return entryIndex The index of the written entry within the batch function writeEntry(bytes32 dataHash) external returns (uint256 dbNonce, uint64 entryIndex); /// @notice Request the given Interchain Modules to verify an existing batch. /// If the batch is not finalized, the module will verify it after finalization. /// For the finalized batch the batch root is already available, and the module can verify it immediately. /// Note: every module has a separate fee paid in the native gas token of the source chain, /// and `msg.value` must be equal to the sum of all fees. /// Note: this method is permissionless, and anyone can request verification for any batch. /// @dev Will revert if the batch with the given nonce does not exist. /// @param dstChainId The chain id of the destination chain /// @param dbNonce The database nonce of the existing batch /// @param srcModules The source chain addresses of the Interchain Modules to use for verification function requestBatchVerification( uint256 dstChainId, uint256 dbNonce, address[] memory srcModules ) external payable; /// @notice Write data to the Interchain DataBase as a new entry in the current batch. /// Then request the Interchain Modules to verify the batch containing the written entry on the destination chain. /// See `writeEntry` and `requestBatchVerification` for more details. /// @dev Will revert if the empty array of modules is provided. /// @param dstChainId The chain id of the destination chain /// @param dataHash The hash of the data to be written to the Interchain DataBase as a new entry /// @param srcModules The source chain addresses of the Interchain Modules to use for verification /// @return dbNonce The database nonce of the batch containing the written entry /// @return entryIndex The index of the written entry within the batch function writeEntryWithVerification( uint256 dstChainId, bytes32 dataHash, address[] memory srcModules ) external payable returns (uint256 dbNonce, uint64 entryIndex); /// @notice Allows the Interchain Module to verify the batch coming from the remote chain. /// Note: The DB will only accept the batch of the same version as the DB itself. /// @param versionedBatch The versioned Interchain Batch to verify function verifyRemoteBatch(bytes memory versionedBatch) external; // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════ /// @notice Get the fee for writing data to the Interchain DataBase, and verifying it on the destination chain /// using the provided Interchain Modules. /// @dev Will revert if the empty array of modules is provided. /// @param dstChainId The chain id of the destination chain /// @param srcModules The source chain addresses of the Interchain Modules to use for verification function getInterchainFee(uint256 dstChainId, address[] memory srcModules) external view returns (uint256); /// @notice Returns the list of leafs of the finalized batch with the given nonce. /// Note: the leafs are ordered by the index of the written entry in the current batch, /// and the leafs value match the value of the written entry (srcWriter + dataHash hashed together). /// @dev Will revert if the batch with the given nonce does not exist, or is not finalized. /// @param dbNonce The database nonce of the finalized batch function getBatchLeafs(uint256 dbNonce) external view returns (bytes32[] memory); /// @notice Returns the list of leafs of the finalized batch with the given nonce, /// paginated by the given start and end indexes. The end index is exclusive. /// Note: this is useful when the batch contains a large number of leafs, and calling `getBatchLeafs` /// would result in a gas limit exceeded error. /// @dev Will revert if the batch with the given nonce does not exist, or is not finalized. /// Will revert if the provided range is invalid. /// @param dbNonce The database nonce of the finalized batch /// @param start The start index of the paginated leafs, inclusive /// @param end The end index of the paginated leafs, exclusive function getBatchLeafsPaginated( uint256 dbNonce, uint64 start, uint64 end ) external view returns (bytes32[] memory); /// @notice Returns the size of the finalized batch with the given nonce. /// @dev Will revert if the batch with the given nonce does not exist, or is not finalized. /// @param dbNonce The database nonce of the finalized batch function getBatchSize(uint256 dbNonce) external view returns (uint64); /// @notice Get the finalized Interchain Batch with the given nonce. /// @dev Will revert if the batch with the given nonce does not exist, or is not finalized. /// @param dbNonce The database nonce of the finalized batch function getBatch(uint256 dbNonce) external view returns (InterchainBatch memory); /// @notice Get the Interchain Entry's value written on the local chain with the given batch nonce and entry index. /// Entry value is calculated as the hash of the writer address and the written data hash. /// Note: the batch does not have to be finalized to fetch the entry value. /// @dev Will revert if the batch with the given nonce does not exist, /// or the entry with the given index does not exist within the batch. /// @param dbNonce The database nonce of the existing batch /// @param entryIndex The index of the written entry within the batch function getEntryValue(uint256 dbNonce, uint64 entryIndex) external view returns (bytes32); /// @notice Get the Merkle proof of inclusion for the entry with the given index /// in the finalized batch with the given nonce. /// @dev Will revert if the batch with the given nonce does not exist, or is not finalized. /// Will revert if the entry with the given index does not exist within the batch. /// @param dbNonce The database nonce of the finalized batch /// @param entryIndex The index of the written entry within the batch /// @return proof The Merkle proof of inclusion for the entry function getEntryProof(uint256 dbNonce, uint64 entryIndex) external view returns (bytes32[] memory proof); /// @notice Get the nonce of the database, which is incremented every time a new batch is finalized. /// This is the nonce of the current non-finalized batch. function getDBNonce() external view returns (uint256); /// @notice Get the index of the next entry to be written to the database. /// @return dbNonce The database nonce of the batch including the next entry /// @return entryIndex The index of the next entry within that batch function getNextEntryIndex() external view returns (uint256 dbNonce, uint64 entryIndex); /// @notice Read the data written on specific source chain by a specific writer, /// and verify it on the destination chain using the provided Interchain Module. /// Note: returned zero value indicates that the module has not verified the entry. /// @param entry The Interchain Entry to read /// @param dstModule The destination chain addresses of the Interchain Modules to use for verification /// @return moduleVerifiedAt The block timestamp at which the entry was verified by the module, /// or ZERO if the module has not verified the entry. function checkVerification( address dstModule, InterchainEntry memory entry, bytes32[] memory proof ) external view returns (uint256 moduleVerifiedAt); /// @notice Get the version of the Interchain DataBase. // solhint-disable-next-line func-name-mixedcase function DB_VERSION() external pure returns (uint16); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @notice Every Module may opt a different method to confirm the verified entries on destination chain, /// therefore this is not a part of a common interface. interface IInterchainModule { error InterchainModule__NotInterchainDB(address caller); error InterchainModule__IncorrectSourceChainId(uint256 chainId); error InterchainModule__InsufficientFee(uint256 actual, uint256 required); error InterchainModule__SameChainId(uint256 chainId); /// @notice Request the verification of a batch from the Interchain DataBase by the module. /// If the batch is not yet finalized, the verification on destination chain will be delayed until /// the finalization is done and batch root is saved on the source chain. /// Note: a fee is paid to the module for verification, and could be retrieved by using `getModuleFee`. /// Note: this will eventually trigger `InterchainDB.verifyRemoteBatch(batch)` function on destination chain, /// with no guarantee of ordering. /// @dev Could be only called by the Interchain DataBase contract. /// @param dstChainId The chain id of the destination chain /// @param versionedBatch The versioned batch to verify function requestBatchVerification(uint256 dstChainId, bytes memory versionedBatch) external payable; /// @notice Get the Module fee for verifying a batch on the specified destination chain. /// @param dstChainId The chain id of the destination chain /// @param dbNonce The database nonce of the batch on the source chain function getModuleFee(uint256 dstChainId, uint256 dbNonce) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {VersionedPayloadLib} from "./VersionedPayload.sol"; /// @notice Struct representing a batch of entries in the Interchain DataBase. /// Batched entries are put together in a Merkle tree, which root is saved. /// Batch has a globally unique identifier (key) and a value. /// - key: srcChainId + dbNonce /// - value: batchRoot /// @param srcChainId The chain id of the source chain /// @param dbNonce The database nonce of the batch /// @param batchRoot The root of the Merkle tree containing the batched entries struct InterchainBatch { // TODO: can we use uint64 for chain id? uint256 srcChainId; uint256 dbNonce; bytes32 batchRoot; } library InterchainBatchLib { using VersionedPayloadLib for bytes; /// @notice Constructs an InterchainBatch struct to be saved on the local chain. /// @param dbNonce The database nonce of the batch /// @param batchRoot The root of the Merkle tree containing the batched entries /// @return batch The constructed InterchainBatch struct function constructLocalBatch( uint256 dbNonce, bytes32 batchRoot ) internal view returns (InterchainBatch memory batch) { return InterchainBatch({srcChainId: block.chainid, dbNonce: dbNonce, batchRoot: batchRoot}); } /// @notice Encodes the InterchainBatch struct into a non-versioned batch payload. function encodeBatch(InterchainBatch memory batch) internal pure returns (bytes memory) { return abi.encode(batch); } /// @notice Decodes the InterchainBatch struct from a non-versioned batch payload in calldata. function decodeBatch(bytes calldata data) internal pure returns (InterchainBatch memory) { return abi.decode(data, (InterchainBatch)); } /// @notice Decodes the InterchainBatch struct from a non-versioned batch payload in memory. function decodeBatchFromMemory(bytes memory data) internal pure returns (InterchainBatch memory) { return abi.decode(data, (InterchainBatch)); } /// @notice Returns the globally unique identifier of the batch function batchKey(InterchainBatch memory batch) internal pure returns (bytes32) { return keccak256(abi.encode(batch.srcChainId, batch.dbNonce)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {TypeCasts} from "./TypeCasts.sol"; /// @notice Struct representing an entry in the Interchain DataBase. /// Entry has a globally unique identifier (key) and a value. /// - key: srcChainId + dbNonce + entryIndex /// - value: srcWriter + dataHash /// @param srcChainId The chain id of the source chain /// @param dbNonce The database nonce of the batch containing the entry /// @param entryIndex The index of the entry in the batch /// @param srcWriter The address of the writer on the source chain /// @param dataHash The hash of the data written on the source chain struct InterchainEntry { // TODO: can we use uint64 for chain id? uint256 srcChainId; uint256 dbNonce; uint64 entryIndex; bytes32 srcWriter; bytes32 dataHash; } using InterchainEntryLib for InterchainEntry global; 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 writer The address of the writer on the local chain /// @param dataHash The hash of the data written on the local chain /// @return entry The constructed InterchainEntry struct function constructLocalEntry( uint256 dbNonce, uint64 entryIndex, address writer, bytes32 dataHash ) internal view returns (InterchainEntry memory entry) { return InterchainEntry({ srcChainId: block.chainid, dbNonce: dbNonce, entryIndex: entryIndex, srcWriter: TypeCasts.addressToBytes32(writer), dataHash: dataHash }); } /// @notice Returns the globally unique identifier of the entry function entryKey(InterchainEntry memory entry) internal pure returns (bytes32) { return keccak256(abi.encode(entry.srcChainId, entry.dbNonce, entry.entryIndex)); } /// @notice Returns the value of the entry: writer + dataHash hashed together function entryValue(InterchainEntry memory entry) internal pure returns (bytes32) { return keccak256(abi.encode(entry.srcWriter, entry.dataHash)); } /// @notice Returns the globally unique identifier of the batch containing the entry function batchKey(InterchainEntry memory entry) internal pure returns (bytes32) { return keccak256(abi.encode(entry.srcChainId, entry.dbNonce)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // 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__TooShort(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__TooShort(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__TooShort(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__TooShort(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__TooShort(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 pragma solidity ^0.8.0; 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))); } }
{ "remappings": [ "@openzeppelin/=node_modules/@openzeppelin/", "@synapsecns/=node_modules/@synapsecns/", "ds-test/=node_modules/ds-test/src/", "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": {} }
Contract ABI
API[{"inputs":[{"internalType":"uint256","name":"dbNonce","type":"uint256"}],"name":"InterchainDB__BatchDoesNotExist","type":"error"},{"inputs":[{"internalType":"uint256","name":"dbNonce","type":"uint256"}],"name":"InterchainDB__BatchNotFinalized","type":"error"},{"inputs":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes32","name":"existingBatchRoot","type":"bytes32"},{"components":[{"internalType":"uint256","name":"srcChainId","type":"uint256"},{"internalType":"uint256","name":"dbNonce","type":"uint256"},{"internalType":"bytes32","name":"batchRoot","type":"bytes32"}],"internalType":"struct InterchainBatch","name":"newBatch","type":"tuple"}],"name":"InterchainDB__ConflictingBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"dbNonce","type":"uint256"},{"internalType":"uint64","name":"entryIndex","type":"uint64"},{"internalType":"uint64","name":"batchSize","type":"uint64"}],"name":"InterchainDB__EntryIndexOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"actualFee","type":"uint256"},{"internalType":"uint256","name":"expectedFee","type":"uint256"}],"name":"InterchainDB__IncorrectFeeAmount","type":"error"},{"inputs":[{"internalType":"uint16","name":"version","type":"uint16"}],"name":"InterchainDB__InvalidBatchVersion","type":"error"},{"inputs":[{"internalType":"uint256","name":"dbNonce","type":"uint256"},{"internalType":"uint64","name":"start","type":"uint64"},{"internalType":"uint64","name":"end","type":"uint64"}],"name":"InterchainDB__InvalidEntryRange","type":"error"},{"inputs":[],"name":"InterchainDB__NoModulesSpecified","type":"error"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"InterchainDB__SameChainId","type":"error"},{"inputs":[{"internalType":"bytes","name":"versionedPayload","type":"bytes"}],"name":"VersionedPayload__TooShort","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"dstChainId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dbNonce","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"batchRoot","type":"bytes32"},{"indexed":false,"internalType":"address[]","name":"srcModules","type":"address[]"}],"name":"InterchainBatchVerificationRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"module","type":"address"},{"indexed":false,"internalType":"uint256","name":"srcChainId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dbNonce","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"batchRoot","type":"bytes32"}],"name":"InterchainBatchVerified","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"srcChainId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dbNonce","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"srcWriter","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"dataHash","type":"bytes32"}],"name":"InterchainEntryWritten","type":"event"},{"inputs":[],"name":"DB_VERSION","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dstModule","type":"address"},{"components":[{"internalType":"uint256","name":"srcChainId","type":"uint256"},{"internalType":"uint256","name":"dbNonce","type":"uint256"},{"internalType":"uint64","name":"entryIndex","type":"uint64"},{"internalType":"bytes32","name":"srcWriter","type":"bytes32"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"}],"internalType":"struct InterchainEntry","name":"entry","type":"tuple"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"checkVerification","outputs":[{"internalType":"uint256","name":"moduleVerifiedAt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dbNonce","type":"uint256"}],"name":"getBatch","outputs":[{"components":[{"internalType":"uint256","name":"srcChainId","type":"uint256"},{"internalType":"uint256","name":"dbNonce","type":"uint256"},{"internalType":"bytes32","name":"batchRoot","type":"bytes32"}],"internalType":"struct InterchainBatch","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dbNonce","type":"uint256"}],"name":"getBatchLeafs","outputs":[{"internalType":"bytes32[]","name":"leafs","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dbNonce","type":"uint256"},{"internalType":"uint64","name":"start","type":"uint64"},{"internalType":"uint64","name":"end","type":"uint64"}],"name":"getBatchLeafsPaginated","outputs":[{"internalType":"bytes32[]","name":"leafs","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dbNonce","type":"uint256"}],"name":"getBatchSize","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDBNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dbNonce","type":"uint256"},{"internalType":"uint64","name":"entryIndex","type":"uint64"}],"name":"getEntryProof","outputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dbNonce","type":"uint256"},{"internalType":"uint64","name":"entryIndex","type":"uint64"}],"name":"getEntryValue","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"address[]","name":"srcModules","type":"address[]"}],"name":"getInterchainFee","outputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNextEntryIndex","outputs":[{"internalType":"uint256","name":"dbNonce","type":"uint256"},{"internalType":"uint64","name":"entryIndex","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"uint256","name":"dbNonce","type":"uint256"},{"internalType":"address[]","name":"srcModules","type":"address[]"}],"name":"requestBatchVerification","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"versionedBatch","type":"bytes"}],"name":"verifyRemoteBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dataHash","type":"bytes32"}],"name":"writeEntry","outputs":[{"internalType":"uint256","name":"dbNonce","type":"uint256"},{"internalType":"uint64","name":"entryIndex","type":"uint64"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"},{"internalType":"address[]","name":"srcModules","type":"address[]"}],"name":"writeEntryWithVerification","outputs":[{"internalType":"uint256","name":"dbNonce","type":"uint256"},{"internalType":"uint64","name":"entryIndex","type":"uint64"}],"stateMutability":"payable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50611466806100206000396000f3fe6080604052600436106100e85760003560e01c806384b1c8b81161008a578063d63020bb11610059578063d63020bb14610294578063d961a48e146102b4578063f338140e146102d4578063fc7686ec146102e957600080fd5b806384b1c8b814610212578063aa2f06ae14610227578063afa250051461023c578063b955e9b91461025c57600080fd5b80634f84d040116100c65780634f84d040146101845780635ac44282146101a457806367b1f42e146101d157806367c769af146101ff57600080fd5b806315f53956146100ed57806325a1641d1461011a5780632ad8c70614610147575b600080fd5b3480156100f957600080fd5b50610102600181565b60405161ffff90911681526020015b60405180910390f35b34801561012657600080fd5b5061013a610135366004610e79565b610309565b6040516101119190610eb5565b34801561015357600080fd5b50610167610162366004610ef9565b61037a565b604080519283526001600160401b03909116602083015201610111565b34801561019057600080fd5b5061013a61019f366004610f12565b61039e565b3480156101b057600080fd5b506101c46101bf366004610ef9565b6103cb565b6040516101119190610f3e565b3480156101dd57600080fd5b506101f16101ec366004611006565b610434565b604051908152602001610111565b61016761020d3660046110ac565b610507565b6102256102203660046110ac565b610572565b005b34801561023357600080fd5b506101676105b6565b34801561024857600080fd5b506101f1610257366004610f12565b6105cb565b34801561026857600080fd5b5061027c610277366004610ef9565b6105fd565b6040516001600160401b039091168152602001610111565b3480156102a057600080fd5b5061013a6102af366004610ef9565b610626565b3480156102c057600080fd5b506102256102cf3660046110e6565b610681565b3480156102e057600080fd5b506000546101f1565b3480156102f557600080fd5b506101f1610304366004611157565b6107fa565b60606001600160401b03831615158061032c5750816001600160401b0316600114155b15610369576040516376e6dff560e11b8152600481018590526001600160401b038085166024830152831660448201526064015b60405180910390fd5b61037284610626565b949350505050565b600080600061038884610819565b6020810151604090910151909590945092505050565b60606103a9836108d1565b506103b483836108fc565b506040805160008152602081019091525b92915050565b60408051606081018252600080825260208201819052918101919091526103f1826108d1565b506103c5826104018460006105cb565b60408051606080820183526000808352602080840182905292840152825190810183524681529081019390935282015290565b825160009046810361045b57604051637e16f74d60e11b8152466004820152602401610360565b821561046a57600091506104fe565b60408501516001600160401b03161561048657600091506104fe565b6001600160a01b0386166000908152600160205260408120816104a88861095a565b815260200190815260200160002060405180604001604052908160008201548152602001600182015481525050905060006104e28761099d565b9050808260200151146104f65760006104f9565b81515b935050505b50949350505050565b6000808546810361052d57604051637e16f74d60e11b8152466004820152602401610360565b600061053887610819565b60208101516040820151909550935090506000610558856104018461099d565b9050610566898289896109c0565b50505094509492505050565b8346810361059557604051637e16f74d60e11b8152466004820152602401610360565b60006105a0856103cb565b90506105ae868286866109c0565b505050505050565b6000806105c260005490565b92600092509050565b60006105d783836108fc565b600083815481106105ea576105ea6111a2565b9060005260206000200154905092915050565b60008061060983610b64565b905080831061061957600061061c565b60015b60ff169392505050565b6060610631826108d1565b50604080516001808252818301909252906020808301908036833701905050905061065d8260006105cb565b81600081518110610670576106706111a2565b602002602001018181525050919050565b600061068d8383610b8b565b905061ffff81166001146106ba57604051630293290760e11b815261ffff82166004820152602401610360565b60006106ce6106c98585610bbc565b610bfe565b9050468160000151036106fa578051604051637e16f74d60e11b81526004810191909152602401610360565b60006107058261095a565b3360009081526001602081815260408084208585528252808420815180830190925280548083529301549181019190915292935090036107c9576040805180820182524281528482018051602080840191825233600081815260018084528782208a8352845290879020955186559251949092019390935586518388015192518551928352938201529283015260608201527fbdb1c58ad0991a7df73dd7d1e0c63ba29dd69af7d09838990eef8127de1a548c9060800160405180910390a16105ae565b82604001518160200151146105ae5760208101516040516327b8099d60e11b815261036091339186906004016111b8565b60006108108461080960005490565b8585610c2e565b95945050505050565b6040805160a081018252600080825260208201819052918101829052606081018290526080810182905290546108529060003385610d9b565b9050600061085f8261099d565b81546001810183556000928352602092839020015581015160608201516040517f8adbf0953083a65c138963c649cd1eabd31fa900ecd1cd5d6b5b530fbfa41771926108c4924692879093845260208401929092526040830152606082015260800190565b60405180910390a1919050565b6000548082106108f757604051633e85a07b60e21b815260048101839052602401610360565b919050565b6000610907836105fd565b9050806001600160401b0316826001600160401b03161061095557604051633acda1b760e11b8152600481018490526001600160401b03808416602483015282166044820152606401610360565b505050565b600081600001518260200151604051602001610980929190918252602082015260400190565b604051602081830303815290604052805190602001209050919050565b606080820151608083015160408051602081019390935282015260009101610980565b6000806109d38686602001518686610c2e565b9150915080341015610a0157604051630fb7d66160e41b815234600482015260248101829052604401610360565b80341115610a3e57610a138134611206565b82600081518110610a2657610a266111a2565b60200260200101818151610a3a9190611219565b9052505b826000610a546001610a4f89610e0d565b610e36565b905060005b82811015610b1257868682818110610a7357610a736111a2565b9050602002016020810190610a88919061122c565b6001600160a01b0316634bd7e4dd868381518110610aa857610aa86111a2565b60200260200101518b856040518463ffffffff1660e01b8152600401610acf92919061126b565b6000604051808303818588803b158015610ae857600080fd5b505af1158015610afc573d6000803e3d6000fd5b505050505080610b0b906112a5565b9050610a59565b507f9f201dd0d5465cd198596655528d58e40b6ee2715d5e8bdab49f7e1b1dde771788886020015189604001518989604051610b529594939291906112be565b60405180910390a15050505050505050565b600054808211156108f757604051631de809a760e21b815260048101839052602401610360565b60006002821015610bb35782826040516332ce7cfd60e11b8152600401610360929190611325565b50503560f01c90565b3660006002831015610be55783836040516332ce7cfd60e11b8152600401610360929190611325565b610bf28360028187611354565b915091505b9250929050565b6040805160608101825260008082526020820181905291810191909152610c278284018461137e565b9392505050565b6060600082808203610c5357604051634c65249560e11b815260040160405180910390fd5b806001600160401b03811115610c6b57610c6b610f76565b604051908082528060200260200182016040528015610c94578160200160208202803683370190505b50925060005b81811015610d9057858582818110610cb457610cb46111a2565b9050602002016020810190610cc9919061122c565b604051632508a7b960e11b8152600481018a9052602481018990526001600160a01b039190911690634a114f7290604401602060405180830381865afa158015610d17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3b91906113e7565b848281518110610d4d57610d4d6111a2565b602002602001018181525050838181518110610d6b57610d6b6111a2565b602002602001015183610d7e9190611219565b9250610d89816112a5565b9050610c9a565b505094509492505050565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526040518060a00160405280468152602001868152602001856001600160401b03168152602001610dfc856001600160a01b031690565b815260200192909252509392505050565b606081604051602001610e209190610f3e565b6040516020818303038152906040529050919050565b60608282604051602001610e4b929190611400565b604051602081830303815290604052905092915050565b80356001600160401b03811681146108f757600080fd5b600080600060608486031215610e8e57600080fd5b83359250610e9e60208501610e62565b9150610eac60408501610e62565b90509250925092565b6020808252825182820181905260009190848201906040850190845b81811015610eed57835183529284019291840191600101610ed1565b50909695505050505050565b600060208284031215610f0b57600080fd5b5035919050565b60008060408385031215610f2557600080fd5b82359150610f3560208401610e62565b90509250929050565b815181526020808301519082015260408083015190820152606081016103c5565b80356001600160a01b03811681146108f757600080fd5b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715610fbc57634e487b7160e01b600052604160045260246000fd5b60405290565b60008083601f840112610fd457600080fd5b5081356001600160401b03811115610feb57600080fd5b6020830191508360208260051b8501011115610bf757600080fd5b60008060008084860360e081121561101d57600080fd5b61102686610f5f565b945060a0601f198201121561103a57600080fd5b50611043610f8c565b602086013581526040860135602082015261106060608701610e62565b6040820152608086810135606083015260a087013590820152925060c08501356001600160401b0381111561109457600080fd5b6110a087828801610fc2565b95989497509550505050565b600080600080606085870312156110c257600080fd5b843593506020850135925060408501356001600160401b0381111561109457600080fd5b600080602083850312156110f957600080fd5b82356001600160401b038082111561111057600080fd5b818501915085601f83011261112457600080fd5b81358181111561113357600080fd5b86602082850101111561114557600080fd5b60209290920196919550909350505050565b60008060006040848603121561116c57600080fd5b8335925060208401356001600160401b0381111561118957600080fd5b61119586828701610fc2565b9497909650939450505050565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b03841681526020810183905260a0810161037260408301848051825260208082015190830152604090810151910152565b634e487b7160e01b600052601160045260246000fd5b818103818111156103c5576103c56111f0565b808201808211156103c5576103c56111f0565b60006020828403121561123e57600080fd5b610c2782610f5f565b60005b8381101561126257818101518382015260200161124a565b50506000910152565b8281526040602082015260008251806040840152611290816060850160208701611247565b601f01601f1916919091016060019392505050565b6000600182016112b7576112b76111f0565b5060010190565b60006080820187835260208781850152866040850152608060608501528185835260a08501905086925060005b86811015611317576001600160a01b0361130485610f5f565b16825292820192908201906001016112eb565b509998505050505050505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b6000808585111561136457600080fd5b8386111561137157600080fd5b5050820193919092039150565b60006060828403121561139057600080fd5b604051606081018181106001600160401b03821117156113c057634e487b7160e01b600052604160045260246000fd5b80604052508235815260208301356020820152604083013560408201528091505092915050565b6000602082840312156113f957600080fd5b5051919050565b61ffff60f01b8360f01b16815260008251611422816002850160208701611247565b91909101600201939250505056fea26469706673582212206f3c3ee0012a4583eaac79c3ca7542f5b8a697eb140d8a18de7c703dd0413fac64736f6c63430008140033
Deployed Bytecode
0x6080604052600436106100e85760003560e01c806384b1c8b81161008a578063d63020bb11610059578063d63020bb14610294578063d961a48e146102b4578063f338140e146102d4578063fc7686ec146102e957600080fd5b806384b1c8b814610212578063aa2f06ae14610227578063afa250051461023c578063b955e9b91461025c57600080fd5b80634f84d040116100c65780634f84d040146101845780635ac44282146101a457806367b1f42e146101d157806367c769af146101ff57600080fd5b806315f53956146100ed57806325a1641d1461011a5780632ad8c70614610147575b600080fd5b3480156100f957600080fd5b50610102600181565b60405161ffff90911681526020015b60405180910390f35b34801561012657600080fd5b5061013a610135366004610e79565b610309565b6040516101119190610eb5565b34801561015357600080fd5b50610167610162366004610ef9565b61037a565b604080519283526001600160401b03909116602083015201610111565b34801561019057600080fd5b5061013a61019f366004610f12565b61039e565b3480156101b057600080fd5b506101c46101bf366004610ef9565b6103cb565b6040516101119190610f3e565b3480156101dd57600080fd5b506101f16101ec366004611006565b610434565b604051908152602001610111565b61016761020d3660046110ac565b610507565b6102256102203660046110ac565b610572565b005b34801561023357600080fd5b506101676105b6565b34801561024857600080fd5b506101f1610257366004610f12565b6105cb565b34801561026857600080fd5b5061027c610277366004610ef9565b6105fd565b6040516001600160401b039091168152602001610111565b3480156102a057600080fd5b5061013a6102af366004610ef9565b610626565b3480156102c057600080fd5b506102256102cf3660046110e6565b610681565b3480156102e057600080fd5b506000546101f1565b3480156102f557600080fd5b506101f1610304366004611157565b6107fa565b60606001600160401b03831615158061032c5750816001600160401b0316600114155b15610369576040516376e6dff560e11b8152600481018590526001600160401b038085166024830152831660448201526064015b60405180910390fd5b61037284610626565b949350505050565b600080600061038884610819565b6020810151604090910151909590945092505050565b60606103a9836108d1565b506103b483836108fc565b506040805160008152602081019091525b92915050565b60408051606081018252600080825260208201819052918101919091526103f1826108d1565b506103c5826104018460006105cb565b60408051606080820183526000808352602080840182905292840152825190810183524681529081019390935282015290565b825160009046810361045b57604051637e16f74d60e11b8152466004820152602401610360565b821561046a57600091506104fe565b60408501516001600160401b03161561048657600091506104fe565b6001600160a01b0386166000908152600160205260408120816104a88861095a565b815260200190815260200160002060405180604001604052908160008201548152602001600182015481525050905060006104e28761099d565b9050808260200151146104f65760006104f9565b81515b935050505b50949350505050565b6000808546810361052d57604051637e16f74d60e11b8152466004820152602401610360565b600061053887610819565b60208101516040820151909550935090506000610558856104018461099d565b9050610566898289896109c0565b50505094509492505050565b8346810361059557604051637e16f74d60e11b8152466004820152602401610360565b60006105a0856103cb565b90506105ae868286866109c0565b505050505050565b6000806105c260005490565b92600092509050565b60006105d783836108fc565b600083815481106105ea576105ea6111a2565b9060005260206000200154905092915050565b60008061060983610b64565b905080831061061957600061061c565b60015b60ff169392505050565b6060610631826108d1565b50604080516001808252818301909252906020808301908036833701905050905061065d8260006105cb565b81600081518110610670576106706111a2565b602002602001018181525050919050565b600061068d8383610b8b565b905061ffff81166001146106ba57604051630293290760e11b815261ffff82166004820152602401610360565b60006106ce6106c98585610bbc565b610bfe565b9050468160000151036106fa578051604051637e16f74d60e11b81526004810191909152602401610360565b60006107058261095a565b3360009081526001602081815260408084208585528252808420815180830190925280548083529301549181019190915292935090036107c9576040805180820182524281528482018051602080840191825233600081815260018084528782208a8352845290879020955186559251949092019390935586518388015192518551928352938201529283015260608201527fbdb1c58ad0991a7df73dd7d1e0c63ba29dd69af7d09838990eef8127de1a548c9060800160405180910390a16105ae565b82604001518160200151146105ae5760208101516040516327b8099d60e11b815261036091339186906004016111b8565b60006108108461080960005490565b8585610c2e565b95945050505050565b6040805160a081018252600080825260208201819052918101829052606081018290526080810182905290546108529060003385610d9b565b9050600061085f8261099d565b81546001810183556000928352602092839020015581015160608201516040517f8adbf0953083a65c138963c649cd1eabd31fa900ecd1cd5d6b5b530fbfa41771926108c4924692879093845260208401929092526040830152606082015260800190565b60405180910390a1919050565b6000548082106108f757604051633e85a07b60e21b815260048101839052602401610360565b919050565b6000610907836105fd565b9050806001600160401b0316826001600160401b03161061095557604051633acda1b760e11b8152600481018490526001600160401b03808416602483015282166044820152606401610360565b505050565b600081600001518260200151604051602001610980929190918252602082015260400190565b604051602081830303815290604052805190602001209050919050565b606080820151608083015160408051602081019390935282015260009101610980565b6000806109d38686602001518686610c2e565b9150915080341015610a0157604051630fb7d66160e41b815234600482015260248101829052604401610360565b80341115610a3e57610a138134611206565b82600081518110610a2657610a266111a2565b60200260200101818151610a3a9190611219565b9052505b826000610a546001610a4f89610e0d565b610e36565b905060005b82811015610b1257868682818110610a7357610a736111a2565b9050602002016020810190610a88919061122c565b6001600160a01b0316634bd7e4dd868381518110610aa857610aa86111a2565b60200260200101518b856040518463ffffffff1660e01b8152600401610acf92919061126b565b6000604051808303818588803b158015610ae857600080fd5b505af1158015610afc573d6000803e3d6000fd5b505050505080610b0b906112a5565b9050610a59565b507f9f201dd0d5465cd198596655528d58e40b6ee2715d5e8bdab49f7e1b1dde771788886020015189604001518989604051610b529594939291906112be565b60405180910390a15050505050505050565b600054808211156108f757604051631de809a760e21b815260048101839052602401610360565b60006002821015610bb35782826040516332ce7cfd60e11b8152600401610360929190611325565b50503560f01c90565b3660006002831015610be55783836040516332ce7cfd60e11b8152600401610360929190611325565b610bf28360028187611354565b915091505b9250929050565b6040805160608101825260008082526020820181905291810191909152610c278284018461137e565b9392505050565b6060600082808203610c5357604051634c65249560e11b815260040160405180910390fd5b806001600160401b03811115610c6b57610c6b610f76565b604051908082528060200260200182016040528015610c94578160200160208202803683370190505b50925060005b81811015610d9057858582818110610cb457610cb46111a2565b9050602002016020810190610cc9919061122c565b604051632508a7b960e11b8152600481018a9052602481018990526001600160a01b039190911690634a114f7290604401602060405180830381865afa158015610d17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3b91906113e7565b848281518110610d4d57610d4d6111a2565b602002602001018181525050838181518110610d6b57610d6b6111a2565b602002602001015183610d7e9190611219565b9250610d89816112a5565b9050610c9a565b505094509492505050565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526040518060a00160405280468152602001868152602001856001600160401b03168152602001610dfc856001600160a01b031690565b815260200192909252509392505050565b606081604051602001610e209190610f3e565b6040516020818303038152906040529050919050565b60608282604051602001610e4b929190611400565b604051602081830303815290604052905092915050565b80356001600160401b03811681146108f757600080fd5b600080600060608486031215610e8e57600080fd5b83359250610e9e60208501610e62565b9150610eac60408501610e62565b90509250925092565b6020808252825182820181905260009190848201906040850190845b81811015610eed57835183529284019291840191600101610ed1565b50909695505050505050565b600060208284031215610f0b57600080fd5b5035919050565b60008060408385031215610f2557600080fd5b82359150610f3560208401610e62565b90509250929050565b815181526020808301519082015260408083015190820152606081016103c5565b80356001600160a01b03811681146108f757600080fd5b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715610fbc57634e487b7160e01b600052604160045260246000fd5b60405290565b60008083601f840112610fd457600080fd5b5081356001600160401b03811115610feb57600080fd5b6020830191508360208260051b8501011115610bf757600080fd5b60008060008084860360e081121561101d57600080fd5b61102686610f5f565b945060a0601f198201121561103a57600080fd5b50611043610f8c565b602086013581526040860135602082015261106060608701610e62565b6040820152608086810135606083015260a087013590820152925060c08501356001600160401b0381111561109457600080fd5b6110a087828801610fc2565b95989497509550505050565b600080600080606085870312156110c257600080fd5b843593506020850135925060408501356001600160401b0381111561109457600080fd5b600080602083850312156110f957600080fd5b82356001600160401b038082111561111057600080fd5b818501915085601f83011261112457600080fd5b81358181111561113357600080fd5b86602082850101111561114557600080fd5b60209290920196919550909350505050565b60008060006040848603121561116c57600080fd5b8335925060208401356001600160401b0381111561118957600080fd5b61119586828701610fc2565b9497909650939450505050565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b03841681526020810183905260a0810161037260408301848051825260208082015190830152604090810151910152565b634e487b7160e01b600052601160045260246000fd5b818103818111156103c5576103c56111f0565b808201808211156103c5576103c56111f0565b60006020828403121561123e57600080fd5b610c2782610f5f565b60005b8381101561126257818101518382015260200161124a565b50506000910152565b8281526040602082015260008251806040840152611290816060850160208701611247565b601f01601f1916919091016060019392505050565b6000600182016112b7576112b76111f0565b5060010190565b60006080820187835260208781850152866040850152608060608501528185835260a08501905086925060005b86811015611317576001600160a01b0361130485610f5f565b16825292820192908201906001016112eb565b509998505050505050505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b6000808585111561136457600080fd5b8386111561137157600080fd5b5050820193919092039150565b60006060828403121561139057600080fd5b604051606081018181106001600160401b03821117156113c057634e487b7160e01b600052604160045260246000fd5b80604052508235815260208301356020820152604083013560408201528091505092915050565b6000602082840312156113f957600080fd5b5051919050565b61ffff60f01b8360f01b16815260008251611422816002850160208701611247565b91909101600201939250505056fea26469706673582212206f3c3ee0012a4583eaac79c3ca7542f5b8a697eb140d8a18de7c703dd0413fac64736f6c63430008140033
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.