Sepolia Testnet

Contract

0x2DeF303EA27a3674bb3a5d017e60B2Ef43312A11

Overview

ETH Balance

0 ETH

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
0x6080604060152052024-05-31 23:04:12102 days ago1717196652IN
 Create: InterchainDB
0 ETH0.000424410.38519856

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
65891192024-08-28 18:42:0014 days ago1724870520
0x2DeF303E...f43312A11
0 ETH
65891192024-08-28 18:42:0014 days ago1724870520
0x2DeF303E...f43312A11
0 ETH
64594272024-08-08 7:56:0034 days ago1723103760
0x2DeF303E...f43312A11
0 ETH
64594272024-08-08 7:56:0034 days ago1723103760
0x2DeF303E...f43312A11
0 ETH
64593702024-08-08 7:43:3634 days ago1723103016
0x2DeF303E...f43312A11
0 ETH
64593702024-08-08 7:43:3634 days ago1723103016
0x2DeF303E...f43312A11
0 ETH
64593652024-08-08 7:42:3634 days ago1723102956
0x2DeF303E...f43312A11
0 ETH
64593652024-08-08 7:42:3634 days ago1723102956
0x2DeF303E...f43312A11
0 ETH
64593152024-08-08 7:30:4834 days ago1723102248
0x2DeF303E...f43312A11
0 ETH
64593152024-08-08 7:30:4834 days ago1723102248
0x2DeF303E...f43312A11
0 ETH
64593112024-08-08 7:30:0034 days ago1723102200
0x2DeF303E...f43312A11
0 ETH
64593112024-08-08 7:30:0034 days ago1723102200
0x2DeF303E...f43312A11
0 ETH
64592372024-08-08 7:10:2434 days ago1723101024
0x2DeF303E...f43312A11
0 ETH
64592372024-08-08 7:10:2434 days ago1723101024
0x2DeF303E...f43312A11
0 ETH
64592142024-08-08 7:05:4834 days ago1723100748
0x2DeF303E...f43312A11
0 ETH
64592142024-08-08 7:05:4834 days ago1723100748
0x2DeF303E...f43312A11
0 ETH
64592142024-08-08 7:05:4834 days ago1723100748
0x2DeF303E...f43312A11
0 ETH
64592142024-08-08 7:05:4834 days ago1723100748
0x2DeF303E...f43312A11
0 ETH
64592142024-08-08 7:05:4834 days ago1723100748
0x2DeF303E...f43312A11
0 ETH
64592142024-08-08 7:05:4834 days ago1723100748
0x2DeF303E...f43312A11
0 ETH
64591572024-08-08 6:53:2434 days ago1723100004
0x2DeF303E...f43312A11
0 ETH
64591572024-08-08 6:53:2434 days ago1723100004
0x2DeF303E...f43312A11
0 ETH
64591232024-08-08 6:46:0034 days ago1723099560
0x2DeF303E...f43312A11
0 ETH
64591232024-08-08 6:46:0034 days ago1723099560
0x2DeF303E...f43312A11
0 ETH
64590882024-08-08 6:38:4834 days ago1723099128
0x2DeF303E...f43312A11
0 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
InterchainDB

Compiler Version
v0.8.24+commit.e11b9ed9

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 9 : InterchainDB.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import {InterchainDBEvents} from "./events/InterchainDBEvents.sol";
import {IInterchainDB} from "./interfaces/IInterchainDB.sol";
import {IInterchainModule} from "./interfaces/IInterchainModule.sol";

import {
    InterchainEntry, InterchainEntryLib, EntryKey, ENTRY_UNVERIFIED, ENTRY_CONFLICT
} from "./libs/InterchainEntry.sol";
import {VersionedPayloadLib} from "./libs/VersionedPayload.sol";
import {TypeCasts} from "./libs/TypeCasts.sol";

import {BitMaps} from "@openzeppelin/contracts/utils/structs/BitMaps.sol";

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

    /// @notice The version of the Interchain DataBase. Must match the version of the entries.
    uint16 public constant DB_VERSION = 1;

    /// @dev Stores the values of entries written to the local chain.
    /// Each entry's value is indexed by its nonce, which corresponds to its position in this array.
    bytes32[] internal _entryValues;

    /// @dev Tracks the timestamp at which a specific module verified a remote entry identified by its nonce and value.
    mapping(address module => mapping(EntryKey entryKey => mapping(bytes32 entryValue => uint256 verifiedAt))) internal
        _verificationTime;
    /// @dev Tracks which nonces have been verified by a given module for a specific remote chain.
    /// Utilizes BitMaps to store 256 boolean values for consecutive nonces in a single storage slot.
    mapping(address module => mapping(uint64 chainId => BitMaps.BitMap nonces)) internal _verifiedNonces;

    /// @dev Checks if the chain id is not the same as the local chain id.
    modifier onlyRemoteChainId(uint64 chainId) {
        if (chainId == block.chainid) {
            revert InterchainDB__ChainIdNotRemote(chainId);
        }
        _;
    }

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

    /// @notice Write a data digest to the Interchain DataBase as a new entry.
    /// Note: there are no guarantees that this entry will be available for reading on any of the remote chains.
    /// Use `requestEntryVerification` to ensure that the entry is available for reading on the destination chain.
    /// @param digest       The digest of the data to be written to the Interchain DataBase
    /// @return dbNonce     The database nonce of the entry
    function writeEntry(bytes32 digest) external returns (uint64 dbNonce) {
        InterchainEntry memory entry = _writeEntry(digest);
        dbNonce = entry.dbNonce;
    }

    /// @notice Request the given Interchain Modules to verify an existing entry.
    /// 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 entry.
    /// Note: will request the verification of an empty entry, if the entry with the given nonce does not exist.
    /// This could be useful for providing the proof of non-existence of the entry.
    /// @param dstChainId    The chain id of the destination chain
    /// @param dbNonce       The database nonce of the existing entry
    /// @param srcModules    The source chain addresses of the Interchain Modules to use for verification
    function requestEntryVerification(
        uint64 dstChainId,
        uint64 dbNonce,
        address[] calldata srcModules
    )
        external
        payable
        onlyRemoteChainId(dstChainId)
    {
        InterchainEntry memory entry = getEntry(dbNonce);
        _requestVerification(dstChainId, entry, srcModules);
    }

    /// @notice Write a data digest to the Interchain DataBase as a new entry.
    /// Then request the Interchain Modules to verify the entry on the destination chain.
    /// See `writeEntry` and `requestEntryVerification` for more details.
    /// @dev Will revert if the empty array of modules is provided.
    /// @param dstChainId   The chain id of the destination chain
    /// @param digest       The digest of the data to be written to the Interchain DataBase
    /// @param srcModules   The source chain addresses of the Interchain Modules to use for verification
    /// @return dbNonce     The database nonce of the entry
    function writeEntryRequestVerification(
        uint64 dstChainId,
        bytes32 digest,
        address[] calldata srcModules
    )
        external
        payable
        onlyRemoteChainId(dstChainId)
        returns (uint64 dbNonce)
    {
        InterchainEntry memory entry = _writeEntry(digest);
        _requestVerification(dstChainId, entry, srcModules);
        return entry.dbNonce;
    }

    // ═══════════════════════════════════════════════ MODULE-FACING ═══════════════════════════════════════════════════

    /// @notice Allows the Interchain Module to verify the entry coming from the remote chain.
    /// The module SHOULD verify the exact finalized entry from the remote chain. If the entry with a given nonce
    /// does not exist, module CAN verify it with an empty entry value.
    /// Once the entry exists, the module SHOULD re-verify the entry with the correct entry value.
    /// Note: The DB will only accept the entry of the same version as the DB itself.
    /// @dev Will revert if the entry with the same nonce but a different non-empty entry value is already verified.
    /// @param encodedEntry   The versioned Interchain Entry to verify
    function verifyRemoteEntry(bytes calldata encodedEntry) external {
        InterchainEntry memory entry = _assertCorrectEntry(encodedEntry);
        uint64 srcChainId = entry.srcChainId;
        uint64 dbNonce = entry.dbNonce;
        bytes32 entryValue = entry.entryValue;
        EntryKey entryKey = InterchainEntryLib.encodeEntryKey({srcChainId: srcChainId, dbNonce: dbNonce});
        // Check if that's the first time module verifies the entry with the given nonce
        if (!_verifiedNonces[msg.sender][srcChainId].get(dbNonce)) {
            // Mark the nonce as verified and save the entry
            _verifiedNonces[msg.sender][srcChainId].set(dbNonce);
            _saveVerifiedEntry(msg.sender, entryKey, entry);
            return;
        }
        // Overwriting an empty (non-existent) entry with a non-empty one is allowed
        if (_verificationTime[msg.sender][entryKey][0] != 0 && entryValue != 0) {
            // Remove verification time for the empty entry and save the new one
            delete _verificationTime[msg.sender][entryKey][0];
            _saveVerifiedEntry(msg.sender, entryKey, entry);
            return;
        }
        // No-op if the entry value is the same as previously verified
        if (_verificationTime[msg.sender][entryKey][entryValue] != 0) {
            return;
        }
        // Overwriting an existing entry with a different one is not allowed
        revert InterchainDB__EntryConflict(msg.sender, entry);
    }

    // ═══════════════════════════════════════════════════ 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[] calldata srcModules) external view returns (uint256 fee) {
        (, fee) = _getModuleFees(dstChainId, srcModules);
    }

    /// @notice Check if the entry is verified by the Interchain Module on the destination chain.
    /// - returned value `ENTRY_UNVERIFIED` indicates that the module has not verified the entry.
    /// - returned value `ENTRY_CONFLICT` indicates that the module has verified a different entry value
    /// for the same entry key.
    /// @param dstModule    The destination chain addresses of the Interchain Modules to use for verification
    /// @param entry        The Interchain Entry to check
    /// @return             The block timestamp at which the entry was verified by the module,
    /// ENTRY_UNVERIFIED if the module has not verified the entry,
    /// ENTRY_CONFLICT if the module has verified a different entry value for the same entry key.
    function checkEntryVerification(
        address dstModule,
        InterchainEntry memory entry
    )
        external
        view
        onlyRemoteChainId(entry.srcChainId)
        returns (uint256)
    {
        uint64 srcChainId = entry.srcChainId;
        uint64 dbNonce = entry.dbNonce;
        EntryKey entryKey = InterchainEntryLib.encodeEntryKey({srcChainId: srcChainId, dbNonce: dbNonce});
        // Check if module verified the exact entry first
        uint256 moduleVerifiedAt = _verificationTime[dstModule][entryKey][entry.entryValue];
        if (moduleVerifiedAt != 0) {
            return moduleVerifiedAt;
        }
        // Otherwise, for this nonce the module either verified a conflicting entry or nothing.
        // Check if the verified nonces set contains the nonce to determine the case.
        return _verifiedNonces[dstModule][srcChainId].get(dbNonce) ? ENTRY_CONFLICT : ENTRY_UNVERIFIED;
    }

    /// @notice Get the versioned Interchain Entry with the given nonce.
    /// Note: will return an entry with an empty value if the entry does not exist.
    /// @param dbNonce      The database nonce of the entry
    function getEncodedEntry(uint64 dbNonce) external view returns (bytes memory) {
        InterchainEntry memory entry = getEntry(dbNonce);
        return VersionedPayloadLib.encodeVersionedPayload({
            version: DB_VERSION,
            payload: InterchainEntryLib.encodeEntry(entry)
        });
    }

    /// @notice Get the Interchain Entry with the given nonce written on the local chain.
    /// @dev Will return an entry with an empty value if the entry does not exist.
    /// @param dbNonce      The database nonce of the entry
    function getEntry(uint64 dbNonce) public view returns (InterchainEntry memory) {
        return InterchainEntryLib.constructLocalEntry({dbNonce: dbNonce, entryValue: getEntryValue(dbNonce)});
    }

    /// @notice Get the Interchain Entry's value written on the local chain with the given nonce.
    /// Entry value is calculated as the hash of the writer address and the written data hash.
    /// @dev Will return an empty value if the entry does not exist.
    /// @param dbNonce      The database nonce of the entry
    function getEntryValue(uint64 dbNonce) public view returns (bytes32) {
        // For non-existent entries, the value is zero
        return dbNonce < getDBNonce() ? _entryValues[dbNonce] : bytes32(0);
    }

    /// @notice Get the nonce of the database, which is incremented every time a new entry is written.
    /// This is the nonce of the next entry to be written.
    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 digest) internal returns (InterchainEntry memory entry) {
        uint64 dbNonce = getDBNonce();
        bytes32 srcWriter = TypeCasts.addressToBytes32(msg.sender);
        bytes32 entryValue = InterchainEntryLib.getEntryValue({srcWriter: msg.sender, digest: digest});
        _entryValues.push(entryValue);
        entry = InterchainEntryLib.constructLocalEntry({dbNonce: dbNonce, entryValue: entryValue});
        emit InterchainEntryWritten({dbNonce: dbNonce, srcWriter: srcWriter, digest: digest, entryValue: 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,
        InterchainEntry memory entry,
        address[] calldata srcModules
    )
        internal
    {
        (uint256[] memory fees, uint256 totalFee) = _getModuleFees(dstChainId, 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 versionedEntry = VersionedPayloadLib.encodeVersionedPayload({
            version: DB_VERSION,
            payload: InterchainEntryLib.encodeEntry(entry)
        });
        for (uint256 i = 0; i < len; ++i) {
            IInterchainModule(srcModules[i]).requestEntryVerification{value: fees[i]}(dstChainId, versionedEntry);
        }
        emit InterchainEntryVerificationRequested(dstChainId, entry.dbNonce, srcModules);
    }

    /// @dev Save the verified entry to the database and emit the event.
    function _saveVerifiedEntry(address module, EntryKey entryKey, InterchainEntry memory entry) internal {
        _verificationTime[module][entryKey][entry.entryValue] = block.timestamp;
        emit InterchainEntryVerified(module, entry.srcChainId, entry.dbNonce, entry.entryValue);
    }

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

    /// @dev Asserts that the entry version is correct and that entry originates from a remote chain.
    /// Note: returns the decoded entry for chaining purposes.
    function _assertCorrectEntry(bytes calldata versionedEntry) internal view returns (InterchainEntry memory entry) {
        uint16 dbVersion = versionedEntry.getVersion();
        if (dbVersion != DB_VERSION) {
            revert InterchainDB__EntryVersionMismatch(dbVersion, DB_VERSION);
        }
        entry = InterchainEntryLib.decodeEntry(versionedEntry.getPayload());
        if (entry.srcChainId == block.chainid) {
            revert InterchainDB__ChainIdNotRemote(entry.srcChainId);
        }
    }

    /// @dev Get the verification fees for the modules
    function _getModuleFees(
        uint64 dstChainId,
        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);
            totalFee += fees[i];
        }
    }
}

File 2 of 9 : 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 written entry.
    /// @param srcWriter    The address of the entry writer.
    /// @param digest       The written data digest.
    /// @param entryValue   The value of the written entry: keccak256(abi.encode(srcWriter, digest)).
    event InterchainEntryWritten(uint64 indexed dbNonce, bytes32 indexed srcWriter, bytes32 digest, bytes32 entryValue);

    /// @notice Emitted when a remote entry is verified by the Interchain Module.
    /// @param module       The address of the Interchain Module that verified the entry.
    /// @param srcChainId   The ID of the source chain.
    /// @param dbNonce      The nonce of the verified entry.
    /// @param entryValue   The value of the verified entry: keccak256(abi.encode(srcWriter, digest)).
    event InterchainEntryVerified(
        address indexed module, uint64 indexed srcChainId, uint64 indexed dbNonce, bytes32 entryValue
    );

    /// @notice Emitted when a local entry 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 entry to be verified.
    /// @param srcModules   The addresses of the Interchain Modules that will verify the entry.
    event InterchainEntryVerificationRequested(uint64 indexed dstChainId, uint64 indexed dbNonce, address[] srcModules);
}

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

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

interface IInterchainDB {
    error InterchainDB__ChainIdNotRemote(uint64 chainId);
    error InterchainDB__EntryConflict(address module, InterchainEntry newEntry);
    error InterchainDB__EntryVersionMismatch(uint16 version, uint16 required);
    error InterchainDB__FeeAmountBelowMin(uint256 feeAmount, uint256 minRequired);
    error InterchainDB__ModulesNotProvided();

    function writeEntry(bytes32 digest) external returns (uint64 dbNonce);

    function requestEntryVerification(
        uint64 dstChainId,
        uint64 dbNonce,
        address[] memory srcModules
    )
        external
        payable;

    function writeEntryRequestVerification(
        uint64 dstChainId,
        bytes32 digest,
        address[] memory srcModules
    )
        external
        payable
        returns (uint64 dbNonce);

    function verifyRemoteEntry(bytes memory encodedEntry) external;

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

    function getInterchainFee(uint64 dstChainId, address[] memory srcModules) external view returns (uint256);

    function getEncodedEntry(uint64 dbNonce) external view returns (bytes memory);
    function getEntry(uint64 dbNonce) external view returns (InterchainEntry memory);
    function getEntryValue(uint64 dbNonce) external view returns (bytes32);

    function getDBNonce() external view returns (uint64);

    function checkEntryVerification(
        address dstModule,
        InterchainEntry memory entry
    )
        external
        view
        returns (uint256 moduleVerifiedAt);

    // solhint-disable-next-line func-name-mixedcase
    function DB_VERSION() external pure returns (uint16);
}

File 4 of 9 : 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);

    function requestEntryVerification(uint64 dstChainId, bytes memory versionedEntry) external payable;

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

    function getModuleFee(uint64 dstChainId) external view returns (uint256);
}

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

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

/// @notice Struct representing an entry in the Interchain DataBase.
/// Entry has a globally unique identifier (key) and a value.
/// Assuming `srcWriter` has written data `digest` on the source chain:
/// - key: (srcChainId, dbNonce)
/// - entryValue = keccak256(srcWriter, digest)
/// @param srcChainId   The chain id of the source chain
/// @param dbNonce      The database nonce of the entry
/// @param entryValue   The entry value
struct InterchainEntry {
    uint64 srcChainId;
    uint64 dbNonce;
    bytes32 entryValue;
}

type EntryKey is uint128;

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

library InterchainEntryLib {
    /// @notice Constructs an InterchainEntry struct to be written on the local chain
    /// @param dbNonce      The database nonce of the entry on the source chain
    /// @param entryValue   The value of the entry
    /// @return entry       The constructed InterchainEntry struct
    function constructLocalEntry(
        uint64 dbNonce,
        bytes32 entryValue
    )
        internal
        view
        returns (InterchainEntry memory entry)
    {
        uint64 srcChainId = SafeCast.toUint64(block.chainid);
        return InterchainEntry({srcChainId: srcChainId, dbNonce: dbNonce, entryValue: entryValue});
    }

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

    /// @notice Returns the value of the entry: writer + digest hashed together.
    /// Note: this is exposed for convenience to avoid typecasts prior to abi-encoding.
    function getEntryValue(address srcWriter, bytes32 digest) internal pure returns (bytes32) {
        return keccak256(abi.encode(srcWriter, digest));
    }

    /// @notice Encodes the InterchainEntry struct into a non-versioned entry payload.
    function encodeEntry(InterchainEntry memory entry) internal pure returns (bytes memory) {
        return abi.encode(encodeEntryKey(entry.srcChainId, entry.dbNonce), entry.entryValue);
    }

    /// @notice Decodes the InterchainEntry struct from a non-versioned entry payload in calldata.
    function decodeEntry(bytes calldata data) internal pure returns (InterchainEntry memory entry) {
        EntryKey key;
        (key, entry.entryValue) = abi.decode(data, (EntryKey, bytes32));
        (entry.srcChainId, entry.dbNonce) = decodeEntryKey(key);
    }

    /// @notice Decodes the InterchainEntry struct from a non-versioned entry payload in memory.
    function decodeEntryFromMemory(bytes memory data) internal pure returns (InterchainEntry memory entry) {
        EntryKey key;
        (key, entry.entryValue) = abi.decode(data, (EntryKey, bytes32));
        (entry.srcChainId, entry.dbNonce) = decodeEntryKey(key);
    }

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

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

File 6 of 9 : VersionedPayload.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

// solhint-disable no-inline-assembly
// solhint-disable ordering
library VersionedPayloadLib {
    /// @notice Amount of bytes reserved for the version (uint16) in the versioned payload
    uint256 internal constant VERSION_LENGTH = 2;

    error VersionedPayload__PayloadTooShort(bytes versionedPayload);
    error VersionedPayload__PrecompileFailed();

    /// @notice Encodes the versioned payload into a single bytes array.
    /// @param version  The payload's version.
    /// @param payload  The payload to encode.
    function encodeVersionedPayload(uint16 version, bytes memory payload) internal pure returns (bytes memory) {
        return abi.encodePacked(version, payload);
    }

    /// @notice Extracts the version from the versioned payload (calldata reference).
    /// @param versionedPayload     The versioned payload (calldata reference).
    function getVersion(bytes calldata versionedPayload) internal pure returns (uint16 version) {
        if (versionedPayload.length < VERSION_LENGTH) {
            revert VersionedPayload__PayloadTooShort(versionedPayload);
        }
        assembly {
            // We are only interested in the highest 16 bits of the loaded full 32 bytes word.
            version := shr(240, calldataload(versionedPayload.offset))
        }
    }

    /// @notice Extracts the payload from the versioned payload (calldata reference).
    /// @dev The extracted payload is also returned as a calldata reference.
    /// @param versionedPayload     The versioned payload.
    function getPayload(bytes calldata versionedPayload) internal pure returns (bytes calldata) {
        if (versionedPayload.length < VERSION_LENGTH) {
            revert VersionedPayload__PayloadTooShort(versionedPayload);
        }
        return versionedPayload[VERSION_LENGTH:];
    }

    /// @notice Extracts the version from the versioned payload (memory reference).
    /// @param versionedPayload     The versioned payload (memory reference).
    function getVersionFromMemory(bytes memory versionedPayload) internal pure returns (uint16 version) {
        if (versionedPayload.length < VERSION_LENGTH) {
            revert VersionedPayload__PayloadTooShort(versionedPayload);
        }
        assembly {
            // We are only interested in the highest 16 bits of the loaded full 32 bytes word.
            // We add 0x20 to skip the length of the bytes array.
            version := shr(240, mload(add(versionedPayload, 0x20)))
        }
    }

    /// @notice Extracts the payload from the versioned payload (memory reference).
    /// @dev The extracted payload is copied into a new memory location. Use `getPayload` when possible
    /// to avoid extra memory allocation.
    /// @param versionedPayload     The versioned payload (memory reference).
    function getPayloadFromMemory(bytes memory versionedPayload) internal view returns (bytes memory payload) {
        if (versionedPayload.length < VERSION_LENGTH) {
            revert VersionedPayload__PayloadTooShort(versionedPayload);
        }
        // Figure how many bytes to copy and allocate the memory for the extracted payload.
        uint256 toCopy;
        unchecked {
            toCopy = versionedPayload.length - VERSION_LENGTH;
        }
        payload = new bytes(toCopy);
        // Use identity precompile (0x04) to copy the payload. Unlike MCOPY, this is available on all EVM chains.
        bool res;
        assembly {
            // We add 0x20 to skip the length of the bytes array.
            // We add 0x02 to skip the 2 bytes reserved for the version.
            // Copy the payload to the previously allocated memory.
            res := staticcall(gas(), 0x04, add(versionedPayload, 0x22), toCopy, add(payload, 0x20), toCopy)
        }
        if (!res) {
            revert VersionedPayload__PrecompileFailed();
        }
    }
}

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

library TypeCasts {
    function addressToBytes32(address addr) internal pure returns (bytes32) {
        return bytes32(uint256(uint160(addr)));
    }

    function bytes32ToAddress(bytes32 b) internal pure returns (address) {
        return address(uint160(uint256(b)));
    }
}

File 8 of 9 : BitMaps.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/BitMaps.sol)
pragma solidity ^0.8.20;

/**
 * @dev Library for managing uint256 to bool mapping in a compact and efficient way, provided the keys are sequential.
 * Largely inspired by Uniswap's https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol[merkle-distributor].
 *
 * BitMaps pack 256 booleans across each bit of a single 256-bit slot of `uint256` type.
 * Hence booleans corresponding to 256 _sequential_ indices would only consume a single slot,
 * unlike the regular `bool` which would consume an entire slot for a single value.
 *
 * This results in gas savings in two ways:
 *
 * - Setting a zero value to non-zero only once every 256 times
 * - Accessing the same warm slot for every 256 _sequential_ indices
 */
library BitMaps {
    struct BitMap {
        mapping(uint256 bucket => uint256) _data;
    }

    /**
     * @dev Returns whether the bit at `index` is set.
     */
    function get(BitMap storage bitmap, uint256 index) internal view returns (bool) {
        uint256 bucket = index >> 8;
        uint256 mask = 1 << (index & 0xff);
        return bitmap._data[bucket] & mask != 0;
    }

    /**
     * @dev Sets the bit at `index` to the boolean `value`.
     */
    function setTo(BitMap storage bitmap, uint256 index, bool value) internal {
        if (value) {
            set(bitmap, index);
        } else {
            unset(bitmap, index);
        }
    }

    /**
     * @dev Sets the bit at `index`.
     */
    function set(BitMap storage bitmap, uint256 index) internal {
        uint256 bucket = index >> 8;
        uint256 mask = 1 << (index & 0xff);
        bitmap._data[bucket] |= mask;
    }

    /**
     * @dev Unsets the bit at `index`.
     */
    function unset(BitMap storage bitmap, uint256 index) internal {
        uint256 bucket = index >> 8;
        uint256 mask = 1 << (index & 0xff);
        bitmap._data[bucket] &= ~mask;
    }
}

File 9 of 9 : 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/",
    "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":"chainId","type":"uint64"}],"name":"InterchainDB__ChainIdNotRemote","type":"error"},{"inputs":[{"internalType":"address","name":"module","type":"address"},{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"uint64","name":"dbNonce","type":"uint64"},{"internalType":"bytes32","name":"entryValue","type":"bytes32"}],"internalType":"struct InterchainEntry","name":"newEntry","type":"tuple"}],"name":"InterchainDB__EntryConflict","type":"error"},{"inputs":[{"internalType":"uint16","name":"version","type":"uint16"},{"internalType":"uint16","name":"required","type":"uint16"}],"name":"InterchainDB__EntryVersionMismatch","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":"dstChainId","type":"uint64"},{"indexed":true,"internalType":"uint64","name":"dbNonce","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"srcModules","type":"address[]"}],"name":"InterchainEntryVerificationRequested","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":"entryValue","type":"bytes32"}],"name":"InterchainEntryVerified","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"dbNonce","type":"uint64"},{"indexed":true,"internalType":"bytes32","name":"srcWriter","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"digest","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"entryValue","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":"entryValue","type":"bytes32"}],"internalType":"struct InterchainEntry","name":"entry","type":"tuple"}],"name":"checkEntryVerification","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDBNonce","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"dbNonce","type":"uint64"}],"name":"getEncodedEntry","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"dbNonce","type":"uint64"}],"name":"getEntry","outputs":[{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"uint64","name":"dbNonce","type":"uint64"},{"internalType":"bytes32","name":"entryValue","type":"bytes32"}],"internalType":"struct InterchainEntry","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"dbNonce","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":[{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"uint64","name":"dbNonce","type":"uint64"},{"internalType":"address[]","name":"srcModules","type":"address[]"}],"name":"requestEntryVerification","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedEntry","type":"bytes"}],"name":"verifyRemoteEntry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"digest","type":"bytes32"}],"name":"writeEntry","outputs":[{"internalType":"uint64","name":"dbNonce","type":"uint64"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"bytes32","name":"digest","type":"bytes32"},{"internalType":"address[]","name":"srcModules","type":"address[]"}],"name":"writeEntryRequestVerification","outputs":[{"internalType":"uint64","name":"dbNonce","type":"uint64"}],"stateMutability":"payable","type":"function"}]

608060405234801561001057600080fd5b506112f7806100206000396000f3fe60806040526004361061009c5760003560e01c80634be46671116100645780634be46671146101755780635fecf58d146101a357806387c59c6f146101b6578063b8ba4ba1146101d6578063d9a8da9a146101f6578063f338140e1461021657600080fd5b80630f4302f7146100a157806315f53956146100b65780632ad8c706146100e35780632cb01ddb1461011b57806330005e5f14610148575b600080fd5b6100b46100af366004610dd5565b61022b565b005b3480156100c257600080fd5b506100cb600181565b60405161ffff90911681526020015b60405180910390f35b3480156100ef57600080fd5b506101036100fe366004610e35565b610286565b6040516001600160401b0390911681526020016100da565b34801561012757600080fd5b5061013b610136366004610e4e565b61029d565b6040516100da9190610e69565b34801561015457600080fd5b50610168610163366004610e4e565b6102d2565b6040516100da9190610ee8565b34801561018157600080fd5b50610195610190366004610e4e565b6102fb565b6040519081526020016100da565b6101036101b1366004610efb565b61034b565b3480156101c257600080fd5b506101956101d1366004610f69565b6103a9565b3480156101e257600080fd5b506101956101f1366004611000565b6104ad565b34801561020257600080fd5b506100b4610211366004611052565b6104c3565b34801561022257600080fd5b50600054610103565b8346816001600160401b03160361026557604051630d9e106b60e41b81526001600160401b03821660048201526024015b60405180910390fd5b60006102708561029d565b905061027e86828686610673565b505050505050565b60008061029283610811565b602001519392505050565b60408051606081018252600080825260208201819052918101919091526102cc826102c7846102fb565b6108ed565b92915050565b606060006102df8361029d565b90506102f460016102ef83610940565b6109a4565b9392505050565b600080546001600160401b0316826001600160401b03161061031e5760006102cc565b6000826001600160401b03168154811061033a5761033a6110c3565b906000526020600020015492915050565b60008446816001600160401b03160361038257604051630d9e106b60e41b81526001600160401b038216600482015260240161025c565b600061038d86610811565b905061039b87828787610673565b602001519695505050505050565b8051600090466001600160401b038216036103e257604051630d9e106b60e41b81526001600160401b038216600482015260240161025c565b82516020808501516001600160a01b03871660009081526001835260408082206001600160401b03841686831b67ffffffffffffffff60401b1617808452908552818320828a0151845290945290205490919080156104465794506104a692505050565b6001600160a01b03881660009081526002602090815260408083206001600160401b0388168452825280832066ffffffffffffff600888901c168452909152902054600160ff85161b1661049b57600061049f565b6000195b9550505050505b5092915050565b60006104ba8484846109d0565b95945050505050565b60006104cf8383610b35565b8051602082015160408301519293509091600061050784846001600160401b031660409190911b67ffffffffffffffff60401b161790565b3360009081526002602090815260408083206001600160401b0389168452825280832066ffffffffffffff600889901c168452909152902054909150600160ff85161b166105a7573360009081526002602090815260408083206001600160401b0388168452825280832066ffffffffffffff600888901c16845290915290208054600160ff86161b17905561059e338287610bdf565b50505050505050565b3360009081526001602090815260408083206001600160801b03851684528252808320838052909152902054158015906105e057508115155b1561061c573360008181526001602090815260408083206001600160801b0386168452825280832083805290915281205561059e908287610bdf565b3360009081526001602090815260408083206001600160801b03851684528252808320858452909152902054156106565750505050505050565b3385604051631380534f60e21b815260040161025c9291906110d9565b6000806106818685856109d0565b91509150803410156106af5760405163805af60d60e01b81523460048201526024810182905260440161025c565b803411156106ec576106c18134611130565b826000815181106106d4576106d46110c3565b602002602001018181516106e89190611143565b9052505b8260006106fd60016102ef89610940565b905060005b828110156107b55786868281811061071c5761071c6110c3565b90506020020160208101906107319190611156565b6001600160a01b03166325236ac0868381518110610751576107516110c3565b60200260200101518b856040518463ffffffff1660e01b8152600401610778929190611171565b6000604051808303818588803b15801561079157600080fd5b505af11580156107a5573d6000803e3d6000fd5b5050505050806001019050610702565b5086602001516001600160401b0316886001600160401b03167fa1064e82384e82d75ea17667d4a126550e1567f8b9f9f4becdff16181a33262988886040516107ff92919061119b565b60405180910390a35050505050505050565b604080516060808201835260008083526020808401829052838501829052815485513381840181905281880189905287518083038901815291909501909652855195909101949094206001850182559080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563840181905591929161089683826108ed565b935081836001600160401b03167f1539aa0417494a3d8a405ab17e0e24b1278003e1cbed31edf7876ec98594be5c87846040516108dd929190918252602082015260400190565b60405180910390a3505050919050565b604080516060810182526000808252602082018190529181018290529061091346610c69565b604080516060810182526001600160401b0392831681529186166020830152810184905291505092915050565b606061096f826000015183602001516001600160401b031660409190911b67ffffffffffffffff60401b161790565b60408084015181516001600160801b039093166020840152908201526060016040516020818303038152906040529050919050565b606082826040516020016109b99291906111e7565b604051602081830303815290604052905092915050565b60606000828082036109f5576040516322f15d3d60e11b815260040160405180910390fd5b806001600160401b03811115610a0d57610a0d610f53565b604051908082528060200260200182016040528015610a36578160200160208202803683370190505b50925060005b81811015610b2b57858582818110610a5657610a566110c3565b9050602002016020810190610a6b9190611156565b604051637462303560e11b81526001600160401b03891660048201526001600160a01b03919091169063e8c4606a90602401602060405180830381865afa158015610aba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ade9190611217565b848281518110610af057610af06110c3565b602002602001018181525050838181518110610b0e57610b0e6110c3565b602002602001015183610b219190611143565b9250600101610a3c565b5050935093915050565b6040805160608101825260008082526020820181905291810182905290610b5c8484610ca3565b905061ffff8116600114610b9057604051635ef73b2760e11b815261ffff821660048201526001602482015260440161025c565b610ba2610b9d8585610cd4565b610d16565b91504682600001516001600160401b0316036104a6578151604051630d9e106b60e41b81526001600160401b03909116600482015260240161025c565b6001600160a01b03831660008181526001602090815260408083206001600160801b038716845282528083208582018051855290835292819020429055848201518551935191519182526001600160401b0390811694931692917f3b20d053a9bde26c85a1e20c3a1782847557d6c26733713fc7cc26b656f7e73e910160405180910390a4505050565b60006001600160401b03821115610c9f57604080516306dfcc6560e41b815260048101919091526024810183905260440161025c565b5090565b60006002821015610ccb578282604051635840c5b160e11b815260040161025c929190611230565b50503560f01c90565b3660006002831015610cfd578383604051635840c5b160e11b815260040161025c929190611230565b610d0a836002818761125f565b915091505b9250929050565b6040805160608101825260008082526020820181905291810182905290610d3f84840185611289565b60408401529050610d5b816001600160401b03604082901c1691565b6001600160401b0390811660208501521682525092915050565b80356001600160401b0381168114610d8c57600080fd5b919050565b60008083601f840112610da357600080fd5b5081356001600160401b03811115610dba57600080fd5b6020830191508360208260051b8501011115610d0f57600080fd5b60008060008060608587031215610deb57600080fd5b610df485610d75565b9350610e0260208601610d75565b925060408501356001600160401b03811115610e1d57600080fd5b610e2987828801610d91565b95989497509550505050565b600060208284031215610e4757600080fd5b5035919050565b600060208284031215610e6057600080fd5b6102f482610d75565b81516001600160401b0390811682526020808401519091169082015260408083015190820152606081016102cc565b60005b83811015610eb3578181015183820152602001610e9b565b50506000910152565b60008151808452610ed4816020860160208601610e98565b601f01601f19169290920160200192915050565b6020815260006102f46020830184610ebc565b60008060008060608587031215610f1157600080fd5b610f1a85610d75565b93506020850135925060408501356001600160401b03811115610e1d57600080fd5b80356001600160a01b0381168114610d8c57600080fd5b634e487b7160e01b600052604160045260246000fd5b6000808284036080811215610f7d57600080fd5b610f8684610f3c565b92506060601f1982011215610f9a57600080fd5b50604051606081018181106001600160401b0382111715610fcb57634e487b7160e01b600052604160045260246000fd5b604052610fda60208501610d75565b8152610fe860408501610d75565b60208201526060939093013560408401525092909150565b60008060006040848603121561101557600080fd5b61101e84610d75565b925060208401356001600160401b0381111561103957600080fd5b61104586828701610d91565b9497909650939450505050565b6000806020838503121561106557600080fd5b82356001600160401b038082111561107c57600080fd5b818501915085601f83011261109057600080fd5b81358181111561109f57600080fd5b8660208285010111156110b157600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0383168152608081016102f460208301846001600160401b0380825116835280602083015116602084015250604081015160408301525050565b634e487b7160e01b600052601160045260246000fd5b818103818111156102cc576102cc61111a565b808201808211156102cc576102cc61111a565b60006020828403121561116857600080fd5b6102f482610f3c565b6001600160401b03831681526040602082015260006111936040830184610ebc565b949350505050565b60208082528181018390526000908460408401835b868110156111dc576001600160a01b036111c984610f3c565b16825291830191908301906001016111b0565b509695505050505050565b61ffff60f01b8360f01b16815260008251611209816002850160208701610e98565b919091016002019392505050565b60006020828403121561122957600080fd5b5051919050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b6000808585111561126f57600080fd5b8386111561127c57600080fd5b5050820193919092039150565b6000806040838503121561129c57600080fd5b82356001600160801b03811681146112b357600080fd5b94602093909301359350505056fea2646970667358221220c9fb1ca30c88eaf30f9edc4cb4f2c914a5abd6352ec6480a10bcc7bd1162580a64736f6c63430008180033

Deployed Bytecode

0x60806040526004361061009c5760003560e01c80634be46671116100645780634be46671146101755780635fecf58d146101a357806387c59c6f146101b6578063b8ba4ba1146101d6578063d9a8da9a146101f6578063f338140e1461021657600080fd5b80630f4302f7146100a157806315f53956146100b65780632ad8c706146100e35780632cb01ddb1461011b57806330005e5f14610148575b600080fd5b6100b46100af366004610dd5565b61022b565b005b3480156100c257600080fd5b506100cb600181565b60405161ffff90911681526020015b60405180910390f35b3480156100ef57600080fd5b506101036100fe366004610e35565b610286565b6040516001600160401b0390911681526020016100da565b34801561012757600080fd5b5061013b610136366004610e4e565b61029d565b6040516100da9190610e69565b34801561015457600080fd5b50610168610163366004610e4e565b6102d2565b6040516100da9190610ee8565b34801561018157600080fd5b50610195610190366004610e4e565b6102fb565b6040519081526020016100da565b6101036101b1366004610efb565b61034b565b3480156101c257600080fd5b506101956101d1366004610f69565b6103a9565b3480156101e257600080fd5b506101956101f1366004611000565b6104ad565b34801561020257600080fd5b506100b4610211366004611052565b6104c3565b34801561022257600080fd5b50600054610103565b8346816001600160401b03160361026557604051630d9e106b60e41b81526001600160401b03821660048201526024015b60405180910390fd5b60006102708561029d565b905061027e86828686610673565b505050505050565b60008061029283610811565b602001519392505050565b60408051606081018252600080825260208201819052918101919091526102cc826102c7846102fb565b6108ed565b92915050565b606060006102df8361029d565b90506102f460016102ef83610940565b6109a4565b9392505050565b600080546001600160401b0316826001600160401b03161061031e5760006102cc565b6000826001600160401b03168154811061033a5761033a6110c3565b906000526020600020015492915050565b60008446816001600160401b03160361038257604051630d9e106b60e41b81526001600160401b038216600482015260240161025c565b600061038d86610811565b905061039b87828787610673565b602001519695505050505050565b8051600090466001600160401b038216036103e257604051630d9e106b60e41b81526001600160401b038216600482015260240161025c565b82516020808501516001600160a01b03871660009081526001835260408082206001600160401b03841686831b67ffffffffffffffff60401b1617808452908552818320828a0151845290945290205490919080156104465794506104a692505050565b6001600160a01b03881660009081526002602090815260408083206001600160401b0388168452825280832066ffffffffffffff600888901c168452909152902054600160ff85161b1661049b57600061049f565b6000195b9550505050505b5092915050565b60006104ba8484846109d0565b95945050505050565b60006104cf8383610b35565b8051602082015160408301519293509091600061050784846001600160401b031660409190911b67ffffffffffffffff60401b161790565b3360009081526002602090815260408083206001600160401b0389168452825280832066ffffffffffffff600889901c168452909152902054909150600160ff85161b166105a7573360009081526002602090815260408083206001600160401b0388168452825280832066ffffffffffffff600888901c16845290915290208054600160ff86161b17905561059e338287610bdf565b50505050505050565b3360009081526001602090815260408083206001600160801b03851684528252808320838052909152902054158015906105e057508115155b1561061c573360008181526001602090815260408083206001600160801b0386168452825280832083805290915281205561059e908287610bdf565b3360009081526001602090815260408083206001600160801b03851684528252808320858452909152902054156106565750505050505050565b3385604051631380534f60e21b815260040161025c9291906110d9565b6000806106818685856109d0565b91509150803410156106af5760405163805af60d60e01b81523460048201526024810182905260440161025c565b803411156106ec576106c18134611130565b826000815181106106d4576106d46110c3565b602002602001018181516106e89190611143565b9052505b8260006106fd60016102ef89610940565b905060005b828110156107b55786868281811061071c5761071c6110c3565b90506020020160208101906107319190611156565b6001600160a01b03166325236ac0868381518110610751576107516110c3565b60200260200101518b856040518463ffffffff1660e01b8152600401610778929190611171565b6000604051808303818588803b15801561079157600080fd5b505af11580156107a5573d6000803e3d6000fd5b5050505050806001019050610702565b5086602001516001600160401b0316886001600160401b03167fa1064e82384e82d75ea17667d4a126550e1567f8b9f9f4becdff16181a33262988886040516107ff92919061119b565b60405180910390a35050505050505050565b604080516060808201835260008083526020808401829052838501829052815485513381840181905281880189905287518083038901815291909501909652855195909101949094206001850182559080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563840181905591929161089683826108ed565b935081836001600160401b03167f1539aa0417494a3d8a405ab17e0e24b1278003e1cbed31edf7876ec98594be5c87846040516108dd929190918252602082015260400190565b60405180910390a3505050919050565b604080516060810182526000808252602082018190529181018290529061091346610c69565b604080516060810182526001600160401b0392831681529186166020830152810184905291505092915050565b606061096f826000015183602001516001600160401b031660409190911b67ffffffffffffffff60401b161790565b60408084015181516001600160801b039093166020840152908201526060016040516020818303038152906040529050919050565b606082826040516020016109b99291906111e7565b604051602081830303815290604052905092915050565b60606000828082036109f5576040516322f15d3d60e11b815260040160405180910390fd5b806001600160401b03811115610a0d57610a0d610f53565b604051908082528060200260200182016040528015610a36578160200160208202803683370190505b50925060005b81811015610b2b57858582818110610a5657610a566110c3565b9050602002016020810190610a6b9190611156565b604051637462303560e11b81526001600160401b03891660048201526001600160a01b03919091169063e8c4606a90602401602060405180830381865afa158015610aba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ade9190611217565b848281518110610af057610af06110c3565b602002602001018181525050838181518110610b0e57610b0e6110c3565b602002602001015183610b219190611143565b9250600101610a3c565b5050935093915050565b6040805160608101825260008082526020820181905291810182905290610b5c8484610ca3565b905061ffff8116600114610b9057604051635ef73b2760e11b815261ffff821660048201526001602482015260440161025c565b610ba2610b9d8585610cd4565b610d16565b91504682600001516001600160401b0316036104a6578151604051630d9e106b60e41b81526001600160401b03909116600482015260240161025c565b6001600160a01b03831660008181526001602090815260408083206001600160801b038716845282528083208582018051855290835292819020429055848201518551935191519182526001600160401b0390811694931692917f3b20d053a9bde26c85a1e20c3a1782847557d6c26733713fc7cc26b656f7e73e910160405180910390a4505050565b60006001600160401b03821115610c9f57604080516306dfcc6560e41b815260048101919091526024810183905260440161025c565b5090565b60006002821015610ccb578282604051635840c5b160e11b815260040161025c929190611230565b50503560f01c90565b3660006002831015610cfd578383604051635840c5b160e11b815260040161025c929190611230565b610d0a836002818761125f565b915091505b9250929050565b6040805160608101825260008082526020820181905291810182905290610d3f84840185611289565b60408401529050610d5b816001600160401b03604082901c1691565b6001600160401b0390811660208501521682525092915050565b80356001600160401b0381168114610d8c57600080fd5b919050565b60008083601f840112610da357600080fd5b5081356001600160401b03811115610dba57600080fd5b6020830191508360208260051b8501011115610d0f57600080fd5b60008060008060608587031215610deb57600080fd5b610df485610d75565b9350610e0260208601610d75565b925060408501356001600160401b03811115610e1d57600080fd5b610e2987828801610d91565b95989497509550505050565b600060208284031215610e4757600080fd5b5035919050565b600060208284031215610e6057600080fd5b6102f482610d75565b81516001600160401b0390811682526020808401519091169082015260408083015190820152606081016102cc565b60005b83811015610eb3578181015183820152602001610e9b565b50506000910152565b60008151808452610ed4816020860160208601610e98565b601f01601f19169290920160200192915050565b6020815260006102f46020830184610ebc565b60008060008060608587031215610f1157600080fd5b610f1a85610d75565b93506020850135925060408501356001600160401b03811115610e1d57600080fd5b80356001600160a01b0381168114610d8c57600080fd5b634e487b7160e01b600052604160045260246000fd5b6000808284036080811215610f7d57600080fd5b610f8684610f3c565b92506060601f1982011215610f9a57600080fd5b50604051606081018181106001600160401b0382111715610fcb57634e487b7160e01b600052604160045260246000fd5b604052610fda60208501610d75565b8152610fe860408501610d75565b60208201526060939093013560408401525092909150565b60008060006040848603121561101557600080fd5b61101e84610d75565b925060208401356001600160401b0381111561103957600080fd5b61104586828701610d91565b9497909650939450505050565b6000806020838503121561106557600080fd5b82356001600160401b038082111561107c57600080fd5b818501915085601f83011261109057600080fd5b81358181111561109f57600080fd5b8660208285010111156110b157600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0383168152608081016102f460208301846001600160401b0380825116835280602083015116602084015250604081015160408301525050565b634e487b7160e01b600052601160045260246000fd5b818103818111156102cc576102cc61111a565b808201808211156102cc576102cc61111a565b60006020828403121561116857600080fd5b6102f482610f3c565b6001600160401b03831681526040602082015260006111936040830184610ebc565b949350505050565b60208082528181018390526000908460408401835b868110156111dc576001600160a01b036111c984610f3c565b16825291830191908301906001016111b0565b509695505050505050565b61ffff60f01b8360f01b16815260008251611209816002850160208701610e98565b919091016002019392505050565b60006020828403121561122957600080fd5b5051919050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b6000808585111561126f57600080fd5b8386111561127c57600080fd5b5050820193919092039150565b6000806040838503121561129c57600080fd5b82356001600160801b03811681146112b357600080fd5b94602093909301359350505056fea2646970667358221220c9fb1ca30c88eaf30f9edc4cb4f2c914a5abd6352ec6480a10bcc7bd1162580a64736f6c63430008180033

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  ]
[ 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.