Sepolia Testnet

Contract

0x8d50e833331A0D01d6F286881ce2C3A5DAD12e26

Overview

ETH Balance

0 ETH

Multichain Info

N/A
Transaction Hash
Method
Block
From
To

There are no matching entries

> 10 Internal Transactions found.

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block
From
To
58829772024-05-11 20:14:00246 days ago1715458440
0x8d50e833...5DAD12e26
0.0000001 ETH
58829772024-05-11 20:14:00246 days ago1715458440
0x8d50e833...5DAD12e26
0.0000001 ETH
58771092024-05-10 22:39:48247 days ago1715380788
0x8d50e833...5DAD12e26
0.0000001 ETH
58771092024-05-10 22:39:48247 days ago1715380788
0x8d50e833...5DAD12e26
0.0000001 ETH
58770862024-05-10 22:34:36247 days ago1715380476
0x8d50e833...5DAD12e26
0.0000001 ETH
58770862024-05-10 22:34:36247 days ago1715380476
0x8d50e833...5DAD12e26
0.0000001 ETH
58761402024-05-10 19:10:36247 days ago1715368236
0x8d50e833...5DAD12e26
0.0000001 ETH
58761402024-05-10 19:10:36247 days ago1715368236
0x8d50e833...5DAD12e26
0.0000001 ETH
58761282024-05-10 19:08:00247 days ago1715368080
0x8d50e833...5DAD12e26
0.0000001 ETH
58761282024-05-10 19:08:00247 days ago1715368080
0x8d50e833...5DAD12e26
0.0000001 ETH
58760232024-05-10 18:46:12247 days ago1715366772
0x8d50e833...5DAD12e26
0.0000001 ETH
58760232024-05-10 18:46:12247 days ago1715366772
0x8d50e833...5DAD12e26
0.0000001 ETH
58760112024-05-10 18:43:36247 days ago1715366616
0x8d50e833...5DAD12e26
0.0000001 ETH
58760112024-05-10 18:43:36247 days ago1715366616
0x8d50e833...5DAD12e26
0.0000001 ETH
58753802024-05-10 16:28:00247 days ago1715358480
0x8d50e833...5DAD12e26
0.0000001 ETH
58753802024-05-10 16:28:00247 days ago1715358480
0x8d50e833...5DAD12e26
0.0000001 ETH
58753752024-05-10 16:26:48247 days ago1715358408
0x8d50e833...5DAD12e26
0.0000001 ETH
58753752024-05-10 16:26:48247 days ago1715358408
0x8d50e833...5DAD12e26
0.0000001 ETH
58751032024-05-10 15:28:00247 days ago1715354880
0x8d50e833...5DAD12e26
0.0000001 ETH
58751032024-05-10 15:28:00247 days ago1715354880
0x8d50e833...5DAD12e26
0.0000001 ETH
58750062024-05-10 15:07:00247 days ago1715353620
0x8d50e833...5DAD12e26
0.0000001 ETH
58750062024-05-10 15:07:00247 days ago1715353620
0x8d50e833...5DAD12e26
0.0000001 ETH
58710982024-05-10 1:24:36248 days ago1715304276
0x8d50e833...5DAD12e26
0.0000001 ETH
58710982024-05-10 1:24:36248 days ago1715304276
0x8d50e833...5DAD12e26
0.0000001 ETH
58710762024-05-10 1:20:12248 days ago1715304012
0x8d50e833...5DAD12e26
0.0000001 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

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)

File 1 of 10 : InterchainDB.sol
// 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 {BatchingV1Lib} from "./libs/BatchingV1.sol";
import {
    InterchainBatch, InterchainBatchLib, BatchKey, BATCH_UNVERIFIED, BATCH_CONFLICT
} from "./libs/InterchainBatch.sol";
import {InterchainEntry, InterchainEntryLib} from "./libs/InterchainEntry.sol";
import {VersionedPayloadLib} from "./libs/VersionedPayload.sol";
import {TypeCasts} from "./libs/TypeCasts.sol";

contract InterchainDB is InterchainDBEvents, IInterchainDB {
    using VersionedPayloadLib for bytes;

    /// @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;
    }

    uint16 public constant DB_VERSION = 1;

    bytes32[] internal _entryValues;
    mapping(address module => mapping(BatchKey batchKey => RemoteBatch batch)) internal _remoteBatches;

    modifier onlyRemoteChainId(uint64 chainId) {
        if (chainId == block.chainid) {
            revert InterchainDB__ChainIdNotRemote(chainId);
        }
        _;
    }

    // ═══════════════════════════════════════════════ WRITER-FACING ═══════════════════════════════════════════════════

    /// @inheritdoc IInterchainDB
    function writeEntry(bytes32 dataHash) external returns (uint64 dbNonce, uint64 entryIndex) {
        InterchainEntry memory entry = _writeEntry(dataHash);
        (dbNonce, entryIndex) = (entry.dbNonce, entry.entryIndex);
    }

    /// @inheritdoc IInterchainDB
    function requestBatchVerification(
        uint64 dstChainId,
        uint64 dbNonce,
        address[] calldata srcModules
    )
        external
        payable
        onlyRemoteChainId(dstChainId)
    {
        InterchainBatch memory batch = getBatch(dbNonce);
        _requestVerification(dstChainId, batch, srcModules);
    }

    /// @inheritdoc IInterchainDB
    function writeEntryWithVerification(
        uint64 dstChainId,
        bytes32 dataHash,
        address[] calldata srcModules
    )
        external
        payable
        onlyRemoteChainId(dstChainId)
        returns (uint64 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 {
        InterchainBatch memory batch = _assertCorrectBatch(versionedBatch);
        BatchKey batchKey = InterchainBatchLib.encodeBatchKey({srcChainId: batch.srcChainId, dbNonce: batch.dbNonce});
        RemoteBatch memory existingBatch = _remoteBatches[msg.sender][batchKey];
        // Check if that's the first time module verifies the batch
        if (existingBatch.verifiedAt == 0) {
            _saveVerifiedBatch(msg.sender, batchKey, batch);
            return;
        }
        // No-op if the batch root is the same
        if (existingBatch.batchRoot == batch.batchRoot) {
            return;
        }
        // Overwriting an empty (non-existent) batch with a different one is allowed
        if (existingBatch.batchRoot == 0) {
            _saveVerifiedBatch(msg.sender, batchKey, batch);
            return;
        }
        // Overwriting an existing batch with a different one is not allowed
        revert InterchainDB__BatchConflict(msg.sender, existingBatch.batchRoot, batch);
    }

    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════

    /// @inheritdoc IInterchainDB
    function getBatchLeafs(uint64 dbNonce) external view returns (bytes32[] memory leafs) {
        uint256 batchSize = getBatchSize(dbNonce);
        leafs = new bytes32[](batchSize);
        for (uint64 i = 0; i < batchSize; ++i) {
            leafs[i] = getEntryValue(dbNonce, i);
        }
    }

    /// @inheritdoc IInterchainDB
    function getBatchLeafsPaginated(
        uint64 dbNonce,
        uint64 start,
        uint64 end
    )
        external
        view
        returns (bytes32[] memory leafs)
    {
        uint256 size = getBatchSize(dbNonce);
        if (start > end || end > size) {
            revert InterchainDB__EntryRangeInvalid(dbNonce, start, end);
        }
        leafs = new bytes32[](end - start);
        for (uint64 i = start; i < end; ++i) {
            leafs[i - start] = getEntryValue(dbNonce, i);
        }
    }

    /// @inheritdoc IInterchainDB
    function getEntryProof(uint64 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
        _assertEntryExists(dbNonce, entryIndex);
        return new bytes32[](0);
    }

    /// @inheritdoc IInterchainDB
    function getInterchainFee(uint64 dstChainId, address[] calldata srcModules) external view returns (uint256 fee) {
        (, fee) = _getModuleFees(dstChainId, getDBNonce(), srcModules);
    }

    /// @inheritdoc IInterchainDB
    function getNextEntryIndex() external view returns (uint64 dbNonce, uint64 entryIndex) {
        // In "no batching" mode: entry index is 0, batch size is 1
        dbNonce = getDBNonce();
        entryIndex = 0;
    }

    /// @inheritdoc IInterchainDB
    function checkBatchVerification(
        address dstModule,
        InterchainBatch memory batch
    )
        external
        view
        onlyRemoteChainId(batch.srcChainId)
        returns (uint256 moduleVerifiedAt)
    {
        BatchKey batchKey = InterchainBatchLib.encodeBatchKey({srcChainId: batch.srcChainId, dbNonce: batch.dbNonce});
        RemoteBatch memory remoteBatch = _remoteBatches[dstModule][batchKey];
        // Check if module verified anything for this batch key first
        if (remoteBatch.verifiedAt == 0) {
            return BATCH_UNVERIFIED;
        }
        // Check if the batch root matches the one verified by the module
        return remoteBatch.batchRoot == batch.batchRoot ? remoteBatch.verifiedAt : BATCH_CONFLICT;
    }

    /// @inheritdoc IInterchainDB
    function getVersionedBatch(uint64 dbNonce) external view returns (bytes memory versionedBatch) {
        InterchainBatch memory batch = getBatch(dbNonce);
        return VersionedPayloadLib.encodeVersionedPayload({
            version: DB_VERSION,
            payload: InterchainBatchLib.encodeBatch(batch)
        });
    }

    /// @inheritdoc IInterchainDB
    function getBatchRoot(InterchainEntry memory entry, bytes32[] calldata proof) external pure returns (bytes32) {
        return BatchingV1Lib.getBatchRoot({
            srcWriter: entry.srcWriter,
            dataHash: entry.dataHash,
            entryIndex: entry.entryIndex,
            proof: proof
        });
    }

    /// @inheritdoc IInterchainDB
    function getBatchSize(uint64 dbNonce) public view returns (uint64) {
        // In "no batching" mode: the finalized batch size is 1, the pending batch size is 0
        // We also return 0 for non-existent batches
        return dbNonce < getDBNonce() ? 1 : 0;
    }

    /// @inheritdoc IInterchainDB
    function getBatch(uint64 dbNonce) public view returns (InterchainBatch memory) {
        // In "no batching" mode: the batch root is the same as the entry hash.
        // For non-finalized or non-existent batches, the batch root is 0.
        bytes32 batchRoot = dbNonce < getDBNonce() ? getEntryValue(dbNonce, 0) : bytes32(0);
        return InterchainBatchLib.constructLocalBatch(dbNonce, batchRoot);
    }

    /// @inheritdoc IInterchainDB
    function getEntryValue(uint64 dbNonce, uint64 entryIndex) public view returns (bytes32) {
        _assertEntryExists(dbNonce, entryIndex);
        return _entryValues[dbNonce];
    }

    /// @inheritdoc IInterchainDB
    function getDBNonce() public view returns (uint64) {
        // We can do the unsafe cast here as writing more than 2^64 entries is practically impossible
        return uint64(_entryValues.length);
    }

    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════

    /// @dev Write the entry to the database and emit the event.
    function _writeEntry(bytes32 dataHash) internal returns (InterchainEntry memory entry) {
        uint64 dbNonce = getDBNonce();
        entry = InterchainEntryLib.constructLocalEntry({
            dbNonce: dbNonce,
            entryIndex: 0,
            writer: msg.sender,
            dataHash: dataHash
        });
        bytes32 entryValue = entry.entryValue();
        _entryValues.push(entryValue);
        emit InterchainEntryWritten({
            dbNonce: dbNonce,
            entryIndex: 0,
            srcWriter: TypeCasts.addressToBytes32(msg.sender),
            dataHash: dataHash
        });
        // In the InterchainDB V1 the batch is finalized immediately after the entry is written
        emit InterchainBatchFinalized({dbNonce: dbNonce, batchRoot: entryValue});
    }

    /// @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(
        uint64 dstChainId,
        InterchainBatch memory batch,
        address[] calldata srcModules
    )
        internal
    {
        (uint256[] memory fees, uint256 totalFee) = _getModuleFees(dstChainId, batch.dbNonce, srcModules);
        if (msg.value < totalFee) {
            revert InterchainDB__FeeAmountBelowMin(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, batch.dbNonce, versionedBatch
            );
        }
        emit InterchainBatchVerificationRequested(dstChainId, batch.dbNonce, batch.batchRoot, srcModules);
    }

    /// @dev Save the verified batch to the database and emit the event.
    function _saveVerifiedBatch(address module, BatchKey batchKey, InterchainBatch memory batch) internal {
        _remoteBatches[module][batchKey] = RemoteBatch({verifiedAt: block.timestamp, batchRoot: batch.batchRoot});
        emit InterchainBatchVerified(module, batch.srcChainId, batch.dbNonce, batch.batchRoot);
    }

    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════

    /// @dev Asserts that the batch version is correct and that batch originates from a remote chain.
    /// Note: returns the decoded batch for chaining purposes.
    function _assertCorrectBatch(bytes calldata versionedBatch) internal view returns (InterchainBatch memory batch) {
        uint16 dbVersion = versionedBatch.getVersion();
        if (dbVersion != DB_VERSION) {
            revert InterchainDB__BatchVersionMismatch(dbVersion, DB_VERSION);
        }
        batch = InterchainBatchLib.decodeBatch(versionedBatch.getPayload());
        if (batch.srcChainId == block.chainid) {
            revert InterchainDB__ChainIdNotRemote(batch.srcChainId);
        }
    }

    /// @dev Check that the entry index is within the batch size. Also checks that the batch exists.
    function _assertEntryExists(uint64 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(
        uint64 dstChainId,
        uint64 dbNonce,
        address[] calldata srcModules
    )
        internal
        view
        returns (uint256[] memory fees, uint256 totalFee)
    {
        uint256 len = srcModules.length;
        if (len == 0) {
            revert InterchainDB__ModulesNotProvided();
        }
        fees = new uint256[](len);
        for (uint256 i = 0; i < len; ++i) {
            fees[i] = IInterchainModule(srcModules[i]).getModuleFee(dstChainId, dbNonce);
            totalFee += fees[i];
        }
    }
}

File 2 of 10 : InterchainDBEvents.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

abstract contract InterchainDBEvents {
    /// @notice Emitted when a local entry is written to the database.
    /// @param dbNonce      The nonce of the batch containing the entry.
    /// @param entryIndex   The index of the entry within the batch.
    /// @param srcWriter    The address of the writer.
    /// @param dataHash     The written data hash.
    event InterchainEntryWritten(
        uint64 indexed dbNonce, uint64 entryIndex, bytes32 indexed srcWriter, bytes32 dataHash
    );

    /// @notice Emitted when a local batch is finalized.
    /// @param dbNonce      The nonce of the finalized batch.
    /// @param batchRoot    The Merkle root hash of the finalized batch.
    event InterchainBatchFinalized(uint64 indexed dbNonce, bytes32 batchRoot);

    /// @notice Emitted when a remote batch is verified by the Interchain Module.
    /// @param module       The address of the Interchain Module that verified the batch.
    /// @param srcChainId   The ID of the source chain.
    /// @param dbNonce      The nonce of the verified batch.
    /// @param batchRoot    The Merkle root hash of the verified batch.
    event InterchainBatchVerified(
        address indexed module, uint64 indexed srcChainId, uint64 indexed dbNonce, bytes32 batchRoot
    );

    /// @notice Emitted when a local batch is requested to be verified on a remote chain
    /// using the set of Interchain Modules.
    /// @param dstChainId   The ID of the destination chain.
    /// @param dbNonce      The nonce of the batch to be verified.
    /// @param batchRoot    The Merkle root hash of the batch to be verified.
    /// @param srcModules   The addresses of the Interchain Modules that will verify the batch.
    event InterchainBatchVerificationRequested(
        uint64 indexed dstChainId, uint64 indexed dbNonce, bytes32 batchRoot, address[] srcModules
    );
}

File 3 of 10 : IInterchainDB.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {InterchainBatch} from "../libs/InterchainBatch.sol";
import {InterchainEntry} from "../libs/InterchainEntry.sol";

interface IInterchainDB {
    error InterchainDB__BatchConflict(address module, bytes32 existingBatchRoot, InterchainBatch newBatch);
    error InterchainDB__BatchVersionMismatch(uint16 version, uint16 required);
    error InterchainDB__ChainIdNotRemote(uint64 chainId);
    error InterchainDB__EntryIndexOutOfRange(uint64 dbNonce, uint64 entryIndex, uint64 batchSize);
    error InterchainDB__EntryRangeInvalid(uint64 dbNonce, uint64 start, uint64 end);
    error InterchainDB__FeeAmountBelowMin(uint256 feeAmount, uint256 minRequired);
    error InterchainDB__ModulesNotProvided();

    /// @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 (uint64 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(
        uint64 dstChainId,
        uint64 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(
        uint64 dstChainId,
        bytes32 dataHash,
        address[] memory srcModules
    )
        external
        payable
        returns (uint64 dbNonce, uint64 entryIndex);

    /// @notice Allows the Interchain Module to verify the batch coming from the remote chain.
    /// The module SHOULD verify the exact finalized batch from the remote chain. If the batch with a given nonce
    /// is not finalized or does not exist, module CAN verify it with an empty root value. Once the batch is
    /// finalized, the module SHOULD re-verify the batch with the correct root value.
    /// Note: The DB will only accept the batch of the same version as the DB itself.
    /// @dev Will revert if the batch with the same nonce but a different non-empty root is already verified.
    /// @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(uint64 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(uint64 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(
        uint64 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(uint64 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(uint64 dbNonce) external view returns (InterchainBatch memory);

    /// @notice Get the versioned Interchain Batch with the given nonce.
    /// Note: will return a batch with an empty root if the batch does not exist, or is not finalized.
    /// @param dbNonce      The database nonce of the batch
    function getVersionedBatch(uint64 dbNonce) external view returns (bytes 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(uint64 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(uint64 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 (uint64);

    /// @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 (uint64 dbNonce, uint64 entryIndex);

    /// @notice Check if the batch is verified by the Interchain Module on the destination chain.
    /// Note: returned zero value indicates that the module has not verified the batch.
    /// @param dstModule    The destination chain addresses of the Interchain Modules to use for verification
    /// @param batch        The Interchain Batch to check
    /// @return moduleVerifiedAt    The block timestamp at which the batch was verified by the module,
    ///                             or ZERO if the module has not verified the batch.
    function checkBatchVerification(
        address dstModule,
        InterchainBatch memory batch
    )
        external
        view
        returns (uint256 moduleVerifiedAt);

    /// @notice Get the batch root containing the Interchain Entry with the given index.
    /// @param entry         The Interchain Entry to get the batch root for
    /// @param proof         The Merkle proof of inclusion for the entry in the batch
    function getBatchRoot(InterchainEntry memory entry, bytes32[] memory proof) external pure returns (bytes32);

    /// @notice Get the version of the Interchain DataBase.
    // solhint-disable-next-line func-name-mixedcase
    function DB_VERSION() external pure returns (uint16);
}

File 4 of 10 : IInterchainModule.sol
// 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__CallerNotInterchainDB(address caller);
    error InterchainModule__ChainIdNotRemote(uint64 chainId);
    error InterchainModule__FeeAmountBelowMin(uint256 feeAmount, uint256 minRequired);

    /// @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 batchNonce       The nonce of the batch on the source chain
    /// @param versionedBatch   The versioned batch to verify
    function requestBatchVerification(
        uint64 dstChainId,
        uint64 batchNonce,
        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(uint64 dstChainId, uint64 dbNonce) external view returns (uint256);
}

File 5 of 10 : BatchingV1.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {InterchainEntryLib} from "./InterchainEntry.sol";

library BatchingV1Lib {
    error BatchingV1__EntryIndexNotZero(uint64 entryIndex);
    error BatchingV1__ProofNotEmpty();

    /// @notice Get the batch root containing the Interchain Entry with the given index.
    /// @param srcWriter    The entry writer of the source chain
    /// @param dataHash     The hash of the data of the entry
    /// @param entryIndex   The index of the entry in the batch
    /// @param proof        The Merkle proof of inclusion for the entry in the batch
    /// @return batchRoot   The root of the batch containing the entry
    function getBatchRoot(
        bytes32 srcWriter,
        bytes32 dataHash,
        uint64 entryIndex,
        bytes32[] calldata proof
    )
        internal
        pure
        returns (bytes32 batchRoot)
    {
        // In "no batching" mode: entry index is 0, proof is empty
        if (entryIndex != 0) {
            revert BatchingV1__EntryIndexNotZero(entryIndex);
        }
        if (proof.length != 0) {
            revert BatchingV1__ProofNotEmpty();
        }
        // In "no batching" mode: the batch root is the same as the entry value
        return InterchainEntryLib.getEntryValue({srcWriter: srcWriter, dataHash: dataHash});
    }
}

File 6 of 10 : InterchainBatch.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {VersionedPayloadLib} from "./VersionedPayload.sol";

import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";

type BatchKey is uint128;

/// @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 {
    uint64 srcChainId;
    uint64 dbNonce;
    bytes32 batchRoot;
}

/// @dev Signals that the module has not verified any batch with the given key.
uint256 constant BATCH_UNVERIFIED = 0;
/// @dev Signals that the module has verified a conflicting batch with the given key.
uint256 constant BATCH_CONFLICT = type(uint256).max;

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(
        uint64 dbNonce,
        bytes32 batchRoot
    )
        internal
        view
        returns (InterchainBatch memory batch)
    {
        return InterchainBatch({srcChainId: SafeCast.toUint64(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(encodeBatchKey(batch.srcChainId, batch.dbNonce), batch.batchRoot);
    }

    /// @notice Decodes the InterchainBatch struct from a non-versioned batch payload in calldata.
    function decodeBatch(bytes calldata data) internal pure returns (InterchainBatch memory batch) {
        BatchKey key;
        (key, batch.batchRoot) = abi.decode(data, (BatchKey, bytes32));
        (batch.srcChainId, batch.dbNonce) = decodeBatchKey(key);
    }

    /// @notice Decodes the InterchainBatch struct from a non-versioned batch payload in memory.
    function decodeBatchFromMemory(bytes memory data) internal pure returns (InterchainBatch memory batch) {
        BatchKey key;
        (key, batch.batchRoot) = abi.decode(data, (BatchKey, bytes32));
        (batch.srcChainId, batch.dbNonce) = decodeBatchKey(key);
    }

    /// @notice Encodes the uint128 key of the batch from uint64 srcChainId and uint64 dbNonce.
    function encodeBatchKey(uint64 srcChainId, uint64 dbNonce) internal pure returns (BatchKey) {
        return BatchKey.wrap((uint128(srcChainId) << 64) | dbNonce);
    }

    /// @notice Decodes the uint128 key of the batch into uint64 srcChainId and uint64 dbNonce.
    function decodeBatchKey(BatchKey key) internal pure returns (uint64 srcChainId, uint64 dbNonce) {
        srcChainId = uint64(BatchKey.unwrap(key) >> 64);
        dbNonce = uint64(BatchKey.unwrap(key));
    }
}

File 7 of 10 : InterchainEntry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {TypeCasts} from "./TypeCasts.sol";

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.
/// - 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 {
    uint64 srcChainId;
    uint64 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(
        uint64 dbNonce,
        uint64 entryIndex,
        address writer,
        bytes32 dataHash
    )
        internal
        view
        returns (InterchainEntry memory entry)
    {
        return InterchainEntry({
            srcChainId: SafeCast.toUint64(block.chainid),
            dbNonce: dbNonce,
            entryIndex: entryIndex,
            srcWriter: TypeCasts.addressToBytes32(writer),
            dataHash: dataHash
        });
    }

    /// @notice Returns the value of the entry: writer + dataHash hashed together
    function entryValue(InterchainEntry memory entry) internal pure returns (bytes32) {
        return getEntryValue(entry.srcWriter, entry.dataHash);
    }

    /// @notice Returns the value of the entry: writer + dataHash hashed together
    function getEntryValue(bytes32 srcWriter, bytes32 dataHash) internal pure returns (bytes32) {
        return keccak256(abi.encode(srcWriter, dataHash));
    }
}

File 8 of 10 : VersionedPayload.sol
// 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__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();
        }
    }
}

File 9 of 10 : TypeCasts.sol
// 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)));
    }
}

File 10 of 10 : SafeCast.sol
// 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);
    }
}

Settings
{
  "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

[{"inputs":[{"internalType":"uint64","name":"entryIndex","type":"uint64"}],"name":"BatchingV1__EntryIndexNotZero","type":"error"},{"inputs":[],"name":"BatchingV1__ProofNotEmpty","type":"error"},{"inputs":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes32","name":"existingBatchRoot","type":"bytes32"},{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"uint64","name":"dbNonce","type":"uint64"},{"internalType":"bytes32","name":"batchRoot","type":"bytes32"}],"internalType":"struct InterchainBatch","name":"newBatch","type":"tuple"}],"name":"InterchainDB__BatchConflict","type":"error"},{"inputs":[{"internalType":"uint16","name":"version","type":"uint16"},{"internalType":"uint16","name":"required","type":"uint16"}],"name":"InterchainDB__BatchVersionMismatch","type":"error"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"InterchainDB__ChainIdNotRemote","type":"error"},{"inputs":[{"internalType":"uint64","name":"dbNonce","type":"uint64"},{"internalType":"uint64","name":"entryIndex","type":"uint64"},{"internalType":"uint64","name":"batchSize","type":"uint64"}],"name":"InterchainDB__EntryIndexOutOfRange","type":"error"},{"inputs":[{"internalType":"uint64","name":"dbNonce","type":"uint64"},{"internalType":"uint64","name":"start","type":"uint64"},{"internalType":"uint64","name":"end","type":"uint64"}],"name":"InterchainDB__EntryRangeInvalid","type":"error"},{"inputs":[{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"uint256","name":"minRequired","type":"uint256"}],"name":"InterchainDB__FeeAmountBelowMin","type":"error"},{"inputs":[],"name":"InterchainDB__ModulesNotProvided","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"dbNonce","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"batchRoot","type":"bytes32"}],"name":"InterchainBatchFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"dstChainId","type":"uint64"},{"indexed":true,"internalType":"uint64","name":"dbNonce","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"batchRoot","type":"bytes32"},{"indexed":false,"internalType":"address[]","name":"srcModules","type":"address[]"}],"name":"InterchainBatchVerificationRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"module","type":"address"},{"indexed":true,"internalType":"uint64","name":"srcChainId","type":"uint64"},{"indexed":true,"internalType":"uint64","name":"dbNonce","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"batchRoot","type":"bytes32"}],"name":"InterchainBatchVerified","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"dbNonce","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"entryIndex","type":"uint64"},{"indexed":true,"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":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"uint64","name":"dbNonce","type":"uint64"},{"internalType":"bytes32","name":"batchRoot","type":"bytes32"}],"internalType":"struct InterchainBatch","name":"batch","type":"tuple"}],"name":"checkBatchVerification","outputs":[{"internalType":"uint256","name":"moduleVerifiedAt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"dbNonce","type":"uint64"}],"name":"getBatch","outputs":[{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"uint64","name":"dbNonce","type":"uint64"},{"internalType":"bytes32","name":"batchRoot","type":"bytes32"}],"internalType":"struct InterchainBatch","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"dbNonce","type":"uint64"}],"name":"getBatchLeafs","outputs":[{"internalType":"bytes32[]","name":"leafs","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"dbNonce","type":"uint64"},{"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":[{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"uint64","name":"dbNonce","type":"uint64"},{"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":"getBatchRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint64","name":"dbNonce","type":"uint64"}],"name":"getBatchSize","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDBNonce","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"dbNonce","type":"uint64"},{"internalType":"uint64","name":"entryIndex","type":"uint64"}],"name":"getEntryProof","outputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"dbNonce","type":"uint64"},{"internalType":"uint64","name":"entryIndex","type":"uint64"}],"name":"getEntryValue","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address[]","name":"srcModules","type":"address[]"}],"name":"getInterchainFee","outputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNextEntryIndex","outputs":[{"internalType":"uint64","name":"dbNonce","type":"uint64"},{"internalType":"uint64","name":"entryIndex","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"dbNonce","type":"uint64"}],"name":"getVersionedBatch","outputs":[{"internalType":"bytes","name":"versionedBatch","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"uint64","name":"dbNonce","type":"uint64"},{"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":"uint64","name":"dbNonce","type":"uint64"},{"internalType":"uint64","name":"entryIndex","type":"uint64"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"},{"internalType":"address[]","name":"srcModules","type":"address[]"}],"name":"writeEntryWithVerification","outputs":[{"internalType":"uint64","name":"dbNonce","type":"uint64"},{"internalType":"uint64","name":"entryIndex","type":"uint64"}],"stateMutability":"payable","type":"function"}]

608060405234801561001057600080fd5b50611a49806100206000396000f3fe6080604052600436106100fe5760003560e01c8063b8ba4ba111610095578063e39682c111610064578063e39682c1146102e7578063eb20fbfd14610307578063f338140e1461031a578063fc1ebc911461032f578063fec8dfb91461034f57600080fd5b8063b8ba4ba11461025a578063c72657811461027a578063d180db6f146102a7578063d961a48e146102c757600080fd5b80636c49312c116100d15780636c49312c146101cb578063727a5f91146101e0578063888775d914610218578063aa2f06ae1461024557600080fd5b80630166204f1461010357806315f53956146101365780631c679ac11461015e5780632ad8c7061461018b575b600080fd5b34801561010f57600080fd5b5061012361011e366004611354565b61036f565b6040519081526020015b60405180910390f35b34801561014257600080fd5b5061014b600181565b60405161ffff909116815260200161012d565b34801561016a57600080fd5b5061017e610179366004611421565b610392565b60405161012d9190611464565b34801561019757600080fd5b506101ab6101a63660046114a8565b6104d4565b604080516001600160401b0393841681529290911660208301520161012d565b6101de6101d93660046114c1565b6104f8565b005b3480156101ec57600080fd5b506102006101fb366004611521565b61054e565b6040516001600160401b03909116815260200161012d565b34801561022457600080fd5b50610238610233366004611521565b61057d565b60405161012d919061153c565b34801561025157600080fd5b506101ab6105db565b34801561026657600080fd5b5061012361027536600461156b565b6105f0565b34801561028657600080fd5b5061029a610295366004611521565b61060f565b60405161012d9190611600565b3480156102b357600080fd5b506101236102c2366004611613565b610631565b3480156102d357600080fd5b506101de6102e2366004611646565b61066d565b3480156102f357600080fd5b506101236103023660046116ce565b61074e565b6101ab610315366004611765565b610833565b34801561032657600080fd5b50600054610200565b34801561033b57600080fd5b5061017e61034a366004611521565b6108eb565b34801561035b57600080fd5b5061017e61036a366004611613565b6109a2565b600061038a84606001518560800151866040015186866109c4565b949350505050565b6060600061039f8561054e565b6001600160401b03169050826001600160401b0316846001600160401b031611806103d2575080836001600160401b0316115b15610410576040516372833e0d60e01b81526001600160401b0380871660048301528086166024830152841660448201526064015b60405180910390fd5b61041a84846117bc565b6001600160401b03166001600160401b0381111561043a5761043a6112de565b604051908082528060200260200182016040528015610463578160200160208202803683370190505b509150835b836001600160401b0316816001600160401b031610156104cb5761048c8682610631565b8361049787846117bc565b6001600160401b0316815181106104b0576104b06117dc565b60209081029190910101526104c4816117f2565b9050610468565b50509392505050565b60008060006104e284610a48565b6020810151604090910151909590945092505050565b8346816001600160401b03160361052d57604051630d9e106b60e41b81526001600160401b0382166004820152602401610407565b60006105388561057d565b905061054686828686610b8a565b505050505050565b600080546001600160401b0316826001600160401b031610610571576000610574565b60015b60ff1692915050565b6040805160608101825260008082526020820181905291810191909152600080546001600160401b0316836001600160401b0316106105bd5760006105c8565b6105c8836000610631565b90506105d48382610d3f565b9392505050565b6000806105e760005490565b92600092509050565b6000610606846105ff60005490565b8585610d99565b95945050505050565b6060600061061c8361057d565b90506105d4600161062c83610f0f565b610f73565b600061063d8383610f9f565b6000836001600160401b031681548110610659576106596117dc565b906000526020600020015490505b92915050565b60006106798383610ffe565b905060006106aa826000015183602001516001600160401b031660409190911b67ffffffffffffffff60401b161790565b3360009081526001602081815260408084206001600160801b03861685528252808420815180830190925280548083529301549181019190915292935090036106ff576106f83383856110a8565b5050505050565b8260400151816020015103610715575050505050565b602081015160000361072c576106f83383856110a8565b6020810151604051632d54ead760e11b81526104079133918690600401611818565b8051600090466001600160401b0382160361078757604051630d9e106b60e41b81526001600160401b0382166004820152602401610407565b60006107b6846000015185602001516001600160401b031660409190911b67ffffffffffffffff60401b161790565b6001600160a01b03861660009081526001602081815260408084206001600160801b038616855282528084208151808301909252805480835293015491810191909152929350900361080d5760009350505061082c565b846040015181602001511461082457600019610827565b80515b935050505b5092915050565b6000808546816001600160401b03160361086b57604051630d9e106b60e41b81526001600160401b0382166004820152602401610407565b600061087687610a48565b602081015160408201519095509350905060006108d1856108cc84600061066782606001518360800151604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b610d3f565b90506108df89828989610b8a565b50505094509492505050565b606060006108f88361054e565b6001600160401b03169050806001600160401b0381111561091b5761091b6112de565b604051908082528060200260200182016040528015610944578160200160208202803683370190505b50915060005b81816001600160401b0316101561099b576109658482610631565b83826001600160401b031681518110610980576109806117dc565b6020908102919091010152610994816117f2565b905061094a565b5050919050565b60606109ae8383610f9f565b5050604080516000815260208101909152919050565b60006001600160401b038416156109f95760405163d9c5be6160e01b81526001600160401b0385166004820152602401610407565b8115610a1857604051631a9b90c960e11b815260040160405180910390fd5b50506040805160208082019690965280820194909452805180850382018152606090940190525050805191012090565b6040805160a081018252600080825260208201819052918101829052606081018290526080810182905281549091610a839082903386611146565b91506000610ac683600061066782606001518360800151604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b600080546001810182559080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563018190559050336040805160008152602081018790526001600160401b038516917fb68afc0605cd0ae88c5b20fac83239f61bebdf93d94c8f6f6deed8e21cf2fa5d910160405180910390a3816001600160401b03167fdd11870a5e3366ac946d45a056101b609703ff29dae8c7d889a0f3f6ee455ace82604051610b7b91815260200190565b60405180910390a25050919050565b600080610b9d8686602001518686610d99565b9150915080341015610bcb5760405163805af60d60e01b815234600482015260248101829052604401610407565b80341115610c0857610bdd813461185d565b82600081518110610bf057610bf06117dc565b60200260200101818151610c049190611870565b9052505b826000610c19600161062c89610f0f565b905060005b82811015610cdd57868682818110610c3857610c386117dc565b9050602002016020810190610c4d9190611883565b6001600160a01b0316636b8d469f868381518110610c6d57610c6d6117dc565b60200260200101518b8b60200151866040518563ffffffff1660e01b8152600401610c9a9392919061189e565b6000604051808303818588803b158015610cb357600080fd5b505af1158015610cc7573d6000803e3d6000fd5b505050505080610cd6906118ca565b9050610c1e565b5086602001516001600160401b0316886001600160401b03167fddb2a81061691cd55f8c8bfa25d7d6da9dffe61f552c523de1821da5e1910ac189604001518989604051610d2d939291906118e3565b60405180910390a35050505050505050565b60408051606081018252600080825260208201819052918101919091526040518060600160405280610d70466111d2565b6001600160401b03168152602001846001600160401b0316815260200183815250905092915050565b6060600082808203610dbe576040516322f15d3d60e11b815260040160405180910390fd5b806001600160401b03811115610dd657610dd66112de565b604051908082528060200260200182016040528015610dff578160200160208202803683370190505b50925060005b81811015610f0457858582818110610e1f57610e1f6117dc565b9050602002016020810190610e349190611883565b6040516306223d3560e21b81526001600160401b03808b166004830152891660248201526001600160a01b039190911690631888f4d490604401602060405180830381865afa158015610e8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eaf9190611939565b848281518110610ec157610ec16117dc565b602002602001018181525050838181518110610edf57610edf6117dc565b602002602001015183610ef29190611870565b9250610efd816118ca565b9050610e05565b505094509492505050565b6060610f3e826000015183602001516001600160401b031660409190911b67ffffffffffffffff60401b161790565b60408084015181516001600160801b039093166020840152908201526060016040516020818303038152906040529050919050565b60608282604051602001610f88929190611952565b604051602081830303815290604052905092915050565b6000610faa8361054e565b9050806001600160401b0316826001600160401b031610610ff957604051630299215760e31b81526001600160401b038085166004830152808416602483015282166044820152606401610407565b505050565b6040805160608101825260008082526020820181905291810182905290611025848461120c565b905061ffff811660011461105957604051633199e11760e01b815261ffff8216600482015260016024820152604401610407565b61106b611066858561123d565b61127f565b91504682600001516001600160401b03160361082c578151604051630d9e106b60e41b81526001600160401b039091166004820152602401610407565b604080518082018252428152828201805160208084019182526001600160a01b038816600081815260018084528782206001600160801b038b1683528452908790209551865592519490920193909355828501518551925194519485526001600160401b039081169492169290917f76a643c92bd448082982f23dc803017708bcce282ba837e92611b3e876c45927910160405180910390a4505050565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526040518060a00160405280611185466111d2565b6001600160401b03168152602001866001600160401b03168152602001856001600160401b031681526020016111c1856001600160a01b031690565b815260200192909252509392505050565b60006001600160401b0382111561120857604080516306dfcc6560e41b8152600481019190915260248101839052604401610407565b5090565b60006002821015611234578282604051635840c5b160e11b8152600401610407929190611982565b50503560f01c90565b3660006002831015611266578383604051635840c5b160e11b8152600401610407929190611982565b61127383600281876119b1565b915091505b9250929050565b60408051606081018252600080825260208201819052918101829052906112a8848401856119db565b604084015290506112c4816001600160401b03604082901c1691565b6001600160401b0390811660208501521682525092915050565b634e487b7160e01b600052604160045260246000fd5b80356001600160401b038116811461130b57600080fd5b919050565b60008083601f84011261132257600080fd5b5081356001600160401b0381111561133957600080fd5b6020830191508360208260051b850101111561127857600080fd5b600080600083850360c081121561136a57600080fd5b60a081121561137857600080fd5b5060405160a081016001600160401b0382821081831117156113aa57634e487b7160e01b600052604160045260246000fd5b816040526113b7876112f4565b83526113c5602088016112f4565b60208401526113d6604088016112f4565b6040840152606087013560608401526080870135608084015282955060a087013592508083111561140657600080fd5b505061141486828701611310565b9497909650939450505050565b60008060006060848603121561143657600080fd5b61143f846112f4565b925061144d602085016112f4565b915061145b604085016112f4565b90509250925092565b6020808252825182820181905260009190848201906040850190845b8181101561149c57835183529284019291840191600101611480565b50909695505050505050565b6000602082840312156114ba57600080fd5b5035919050565b600080600080606085870312156114d757600080fd5b6114e0856112f4565b93506114ee602086016112f4565b925060408501356001600160401b0381111561150957600080fd5b61151587828801611310565b95989497509550505050565b60006020828403121561153357600080fd5b6105d4826112f4565b81516001600160401b039081168252602080840151909116908201526040808301519082015260608101610667565b60008060006040848603121561158057600080fd5b611589846112f4565b925060208401356001600160401b038111156115a457600080fd5b61141486828701611310565b60005b838110156115cb5781810151838201526020016115b3565b50506000910152565b600081518084526115ec8160208601602086016115b0565b601f01601f19169290920160200192915050565b6020815260006105d460208301846115d4565b6000806040838503121561162657600080fd5b61162f836112f4565b915061163d602084016112f4565b90509250929050565b6000806020838503121561165957600080fd5b82356001600160401b038082111561167057600080fd5b818501915085601f83011261168457600080fd5b81358181111561169357600080fd5b8660208285010111156116a557600080fd5b60209290920196919550909350505050565b80356001600160a01b038116811461130b57600080fd5b60008082840360808112156116e257600080fd5b6116eb846116b7565b92506060601f19820112156116ff57600080fd5b50604051606081018181106001600160401b038211171561173057634e487b7160e01b600052604160045260246000fd5b60405261173f602085016112f4565b815261174d604085016112f4565b60208201526060939093013560408401525092909150565b6000806000806060858703121561177b57600080fd5b611784856112f4565b93506020850135925060408501356001600160401b0381111561150957600080fd5b634e487b7160e01b600052601160045260246000fd5b6001600160401b0382811682821603908082111561082c5761082c6117a6565b634e487b7160e01b600052603260045260246000fd5b60006001600160401b0380831681810361180e5761180e6117a6565b6001019392505050565b6001600160a01b0384168152602080820184905282516001600160401b0390811660408085019190915291840151166060830152820151608082015260a0810161038a565b81810381811115610667576106676117a6565b80820180821115610667576106676117a6565b60006020828403121561189557600080fd5b6105d4826116b7565b60006001600160401b0380861683528085166020840152506060604083015261060660608301846115d4565b6000600182016118dc576118dc6117a6565b5060010190565b83815260406020808301829052908201839052600090849060608401835b8681101561192d576001600160a01b0361191a856116b7565b1682529282019290820190600101611901565b50979650505050505050565b60006020828403121561194b57600080fd5b5051919050565b61ffff60f01b8360f01b168152600082516119748160028501602087016115b0565b919091016002019392505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b600080858511156119c157600080fd5b838611156119ce57600080fd5b5050820193919092039150565b600080604083850312156119ee57600080fd5b82356001600160801b0381168114611a0557600080fd5b94602093909301359350505056fea26469706673582212202b48e2cdc8c436bb57dd8dce706e3103d8bc8ccfdffaf019732d9d17e5e86dee64736f6c63430008140033

Deployed Bytecode

0x6080604052600436106100fe5760003560e01c8063b8ba4ba111610095578063e39682c111610064578063e39682c1146102e7578063eb20fbfd14610307578063f338140e1461031a578063fc1ebc911461032f578063fec8dfb91461034f57600080fd5b8063b8ba4ba11461025a578063c72657811461027a578063d180db6f146102a7578063d961a48e146102c757600080fd5b80636c49312c116100d15780636c49312c146101cb578063727a5f91146101e0578063888775d914610218578063aa2f06ae1461024557600080fd5b80630166204f1461010357806315f53956146101365780631c679ac11461015e5780632ad8c7061461018b575b600080fd5b34801561010f57600080fd5b5061012361011e366004611354565b61036f565b6040519081526020015b60405180910390f35b34801561014257600080fd5b5061014b600181565b60405161ffff909116815260200161012d565b34801561016a57600080fd5b5061017e610179366004611421565b610392565b60405161012d9190611464565b34801561019757600080fd5b506101ab6101a63660046114a8565b6104d4565b604080516001600160401b0393841681529290911660208301520161012d565b6101de6101d93660046114c1565b6104f8565b005b3480156101ec57600080fd5b506102006101fb366004611521565b61054e565b6040516001600160401b03909116815260200161012d565b34801561022457600080fd5b50610238610233366004611521565b61057d565b60405161012d919061153c565b34801561025157600080fd5b506101ab6105db565b34801561026657600080fd5b5061012361027536600461156b565b6105f0565b34801561028657600080fd5b5061029a610295366004611521565b61060f565b60405161012d9190611600565b3480156102b357600080fd5b506101236102c2366004611613565b610631565b3480156102d357600080fd5b506101de6102e2366004611646565b61066d565b3480156102f357600080fd5b506101236103023660046116ce565b61074e565b6101ab610315366004611765565b610833565b34801561032657600080fd5b50600054610200565b34801561033b57600080fd5b5061017e61034a366004611521565b6108eb565b34801561035b57600080fd5b5061017e61036a366004611613565b6109a2565b600061038a84606001518560800151866040015186866109c4565b949350505050565b6060600061039f8561054e565b6001600160401b03169050826001600160401b0316846001600160401b031611806103d2575080836001600160401b0316115b15610410576040516372833e0d60e01b81526001600160401b0380871660048301528086166024830152841660448201526064015b60405180910390fd5b61041a84846117bc565b6001600160401b03166001600160401b0381111561043a5761043a6112de565b604051908082528060200260200182016040528015610463578160200160208202803683370190505b509150835b836001600160401b0316816001600160401b031610156104cb5761048c8682610631565b8361049787846117bc565b6001600160401b0316815181106104b0576104b06117dc565b60209081029190910101526104c4816117f2565b9050610468565b50509392505050565b60008060006104e284610a48565b6020810151604090910151909590945092505050565b8346816001600160401b03160361052d57604051630d9e106b60e41b81526001600160401b0382166004820152602401610407565b60006105388561057d565b905061054686828686610b8a565b505050505050565b600080546001600160401b0316826001600160401b031610610571576000610574565b60015b60ff1692915050565b6040805160608101825260008082526020820181905291810191909152600080546001600160401b0316836001600160401b0316106105bd5760006105c8565b6105c8836000610631565b90506105d48382610d3f565b9392505050565b6000806105e760005490565b92600092509050565b6000610606846105ff60005490565b8585610d99565b95945050505050565b6060600061061c8361057d565b90506105d4600161062c83610f0f565b610f73565b600061063d8383610f9f565b6000836001600160401b031681548110610659576106596117dc565b906000526020600020015490505b92915050565b60006106798383610ffe565b905060006106aa826000015183602001516001600160401b031660409190911b67ffffffffffffffff60401b161790565b3360009081526001602081815260408084206001600160801b03861685528252808420815180830190925280548083529301549181019190915292935090036106ff576106f83383856110a8565b5050505050565b8260400151816020015103610715575050505050565b602081015160000361072c576106f83383856110a8565b6020810151604051632d54ead760e11b81526104079133918690600401611818565b8051600090466001600160401b0382160361078757604051630d9e106b60e41b81526001600160401b0382166004820152602401610407565b60006107b6846000015185602001516001600160401b031660409190911b67ffffffffffffffff60401b161790565b6001600160a01b03861660009081526001602081815260408084206001600160801b038616855282528084208151808301909252805480835293015491810191909152929350900361080d5760009350505061082c565b846040015181602001511461082457600019610827565b80515b935050505b5092915050565b6000808546816001600160401b03160361086b57604051630d9e106b60e41b81526001600160401b0382166004820152602401610407565b600061087687610a48565b602081015160408201519095509350905060006108d1856108cc84600061066782606001518360800151604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b610d3f565b90506108df89828989610b8a565b50505094509492505050565b606060006108f88361054e565b6001600160401b03169050806001600160401b0381111561091b5761091b6112de565b604051908082528060200260200182016040528015610944578160200160208202803683370190505b50915060005b81816001600160401b0316101561099b576109658482610631565b83826001600160401b031681518110610980576109806117dc565b6020908102919091010152610994816117f2565b905061094a565b5050919050565b60606109ae8383610f9f565b5050604080516000815260208101909152919050565b60006001600160401b038416156109f95760405163d9c5be6160e01b81526001600160401b0385166004820152602401610407565b8115610a1857604051631a9b90c960e11b815260040160405180910390fd5b50506040805160208082019690965280820194909452805180850382018152606090940190525050805191012090565b6040805160a081018252600080825260208201819052918101829052606081018290526080810182905281549091610a839082903386611146565b91506000610ac683600061066782606001518360800151604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b600080546001810182559080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563018190559050336040805160008152602081018790526001600160401b038516917fb68afc0605cd0ae88c5b20fac83239f61bebdf93d94c8f6f6deed8e21cf2fa5d910160405180910390a3816001600160401b03167fdd11870a5e3366ac946d45a056101b609703ff29dae8c7d889a0f3f6ee455ace82604051610b7b91815260200190565b60405180910390a25050919050565b600080610b9d8686602001518686610d99565b9150915080341015610bcb5760405163805af60d60e01b815234600482015260248101829052604401610407565b80341115610c0857610bdd813461185d565b82600081518110610bf057610bf06117dc565b60200260200101818151610c049190611870565b9052505b826000610c19600161062c89610f0f565b905060005b82811015610cdd57868682818110610c3857610c386117dc565b9050602002016020810190610c4d9190611883565b6001600160a01b0316636b8d469f868381518110610c6d57610c6d6117dc565b60200260200101518b8b60200151866040518563ffffffff1660e01b8152600401610c9a9392919061189e565b6000604051808303818588803b158015610cb357600080fd5b505af1158015610cc7573d6000803e3d6000fd5b505050505080610cd6906118ca565b9050610c1e565b5086602001516001600160401b0316886001600160401b03167fddb2a81061691cd55f8c8bfa25d7d6da9dffe61f552c523de1821da5e1910ac189604001518989604051610d2d939291906118e3565b60405180910390a35050505050505050565b60408051606081018252600080825260208201819052918101919091526040518060600160405280610d70466111d2565b6001600160401b03168152602001846001600160401b0316815260200183815250905092915050565b6060600082808203610dbe576040516322f15d3d60e11b815260040160405180910390fd5b806001600160401b03811115610dd657610dd66112de565b604051908082528060200260200182016040528015610dff578160200160208202803683370190505b50925060005b81811015610f0457858582818110610e1f57610e1f6117dc565b9050602002016020810190610e349190611883565b6040516306223d3560e21b81526001600160401b03808b166004830152891660248201526001600160a01b039190911690631888f4d490604401602060405180830381865afa158015610e8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eaf9190611939565b848281518110610ec157610ec16117dc565b602002602001018181525050838181518110610edf57610edf6117dc565b602002602001015183610ef29190611870565b9250610efd816118ca565b9050610e05565b505094509492505050565b6060610f3e826000015183602001516001600160401b031660409190911b67ffffffffffffffff60401b161790565b60408084015181516001600160801b039093166020840152908201526060016040516020818303038152906040529050919050565b60608282604051602001610f88929190611952565b604051602081830303815290604052905092915050565b6000610faa8361054e565b9050806001600160401b0316826001600160401b031610610ff957604051630299215760e31b81526001600160401b038085166004830152808416602483015282166044820152606401610407565b505050565b6040805160608101825260008082526020820181905291810182905290611025848461120c565b905061ffff811660011461105957604051633199e11760e01b815261ffff8216600482015260016024820152604401610407565b61106b611066858561123d565b61127f565b91504682600001516001600160401b03160361082c578151604051630d9e106b60e41b81526001600160401b039091166004820152602401610407565b604080518082018252428152828201805160208084019182526001600160a01b038816600081815260018084528782206001600160801b038b1683528452908790209551865592519490920193909355828501518551925194519485526001600160401b039081169492169290917f76a643c92bd448082982f23dc803017708bcce282ba837e92611b3e876c45927910160405180910390a4505050565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526040518060a00160405280611185466111d2565b6001600160401b03168152602001866001600160401b03168152602001856001600160401b031681526020016111c1856001600160a01b031690565b815260200192909252509392505050565b60006001600160401b0382111561120857604080516306dfcc6560e41b8152600481019190915260248101839052604401610407565b5090565b60006002821015611234578282604051635840c5b160e11b8152600401610407929190611982565b50503560f01c90565b3660006002831015611266578383604051635840c5b160e11b8152600401610407929190611982565b61127383600281876119b1565b915091505b9250929050565b60408051606081018252600080825260208201819052918101829052906112a8848401856119db565b604084015290506112c4816001600160401b03604082901c1691565b6001600160401b0390811660208501521682525092915050565b634e487b7160e01b600052604160045260246000fd5b80356001600160401b038116811461130b57600080fd5b919050565b60008083601f84011261132257600080fd5b5081356001600160401b0381111561133957600080fd5b6020830191508360208260051b850101111561127857600080fd5b600080600083850360c081121561136a57600080fd5b60a081121561137857600080fd5b5060405160a081016001600160401b0382821081831117156113aa57634e487b7160e01b600052604160045260246000fd5b816040526113b7876112f4565b83526113c5602088016112f4565b60208401526113d6604088016112f4565b6040840152606087013560608401526080870135608084015282955060a087013592508083111561140657600080fd5b505061141486828701611310565b9497909650939450505050565b60008060006060848603121561143657600080fd5b61143f846112f4565b925061144d602085016112f4565b915061145b604085016112f4565b90509250925092565b6020808252825182820181905260009190848201906040850190845b8181101561149c57835183529284019291840191600101611480565b50909695505050505050565b6000602082840312156114ba57600080fd5b5035919050565b600080600080606085870312156114d757600080fd5b6114e0856112f4565b93506114ee602086016112f4565b925060408501356001600160401b0381111561150957600080fd5b61151587828801611310565b95989497509550505050565b60006020828403121561153357600080fd5b6105d4826112f4565b81516001600160401b039081168252602080840151909116908201526040808301519082015260608101610667565b60008060006040848603121561158057600080fd5b611589846112f4565b925060208401356001600160401b038111156115a457600080fd5b61141486828701611310565b60005b838110156115cb5781810151838201526020016115b3565b50506000910152565b600081518084526115ec8160208601602086016115b0565b601f01601f19169290920160200192915050565b6020815260006105d460208301846115d4565b6000806040838503121561162657600080fd5b61162f836112f4565b915061163d602084016112f4565b90509250929050565b6000806020838503121561165957600080fd5b82356001600160401b038082111561167057600080fd5b818501915085601f83011261168457600080fd5b81358181111561169357600080fd5b8660208285010111156116a557600080fd5b60209290920196919550909350505050565b80356001600160a01b038116811461130b57600080fd5b60008082840360808112156116e257600080fd5b6116eb846116b7565b92506060601f19820112156116ff57600080fd5b50604051606081018181106001600160401b038211171561173057634e487b7160e01b600052604160045260246000fd5b60405261173f602085016112f4565b815261174d604085016112f4565b60208201526060939093013560408401525092909150565b6000806000806060858703121561177b57600080fd5b611784856112f4565b93506020850135925060408501356001600160401b0381111561150957600080fd5b634e487b7160e01b600052601160045260246000fd5b6001600160401b0382811682821603908082111561082c5761082c6117a6565b634e487b7160e01b600052603260045260246000fd5b60006001600160401b0380831681810361180e5761180e6117a6565b6001019392505050565b6001600160a01b0384168152602080820184905282516001600160401b0390811660408085019190915291840151166060830152820151608082015260a0810161038a565b81810381811115610667576106676117a6565b80820180821115610667576106676117a6565b60006020828403121561189557600080fd5b6105d4826116b7565b60006001600160401b0380861683528085166020840152506060604083015261060660608301846115d4565b6000600182016118dc576118dc6117a6565b5060010190565b83815260406020808301829052908201839052600090849060608401835b8681101561192d576001600160a01b0361191a856116b7565b1682529282019290820190600101611901565b50979650505050505050565b60006020828403121561194b57600080fd5b5051919050565b61ffff60f01b8360f01b168152600082516119748160028501602087016115b0565b919091016002019392505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b600080858511156119c157600080fd5b838611156119ce57600080fd5b5050820193919092039150565b600080604083850312156119ee57600080fd5b82356001600160801b0381168114611a0557600080fd5b94602093909301359350505056fea26469706673582212202b48e2cdc8c436bb57dd8dce706e3103d8bc8ccfdffaf019732d9d17e5e86dee64736f6c63430008140033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ 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.